RuntimeError: mat1 and mat2 shapes cannot be multiplied (64x943 and 1x1)
```python
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
from sklearn.model_selection import train_test_split
# 自定义数据集类
class MovieLensDataset(Dataset):
def __init__(self, ratings, user_features, item_features):
self.ratings = ratings
self.user_features = user_features
self.item_features = item_features
def __len__(self):
return len(self.ratings)
def __getitem__(self, idx):
user_id = self.ratings.iloc[idx]['user_id']
movie_id = self.ratings.iloc[idx]['movie_id']
rating = self.ratings.iloc[idx]['rating']
user_feature = self.user_features[user_id]
item_feature = self.item_features[movie_id]
return torch.FloatTensor(user_feature), torch.FloatTensor(item_feature), torch.FloatTensor([rating])
# 定义多模态自注意力层
class MultiModalAttention(nn.Module):
def __init__(self, input_dim, output_dim):
super(MultiModalAttention, self).__init__()
# 直接使用 input_dim 作为 embed_dim
self.embed_dim = input_dim
self.attention = nn.MultiheadAttention(embed_dim=self.embed_dim, num_heads=5)
self.fc = nn.Linear(self.embed_dim, output_dim)
def forward(self, x):
attn_output, _ = self.attention(x, x, x)
return self.fc(attn_output)
# 定义邻域感知层
class NeighborhoodAwareLayer(nn.Module):
def __init__(self, input_dim):
super(NeighborhoodAwareLayer, self).__init__()
self.fc = nn.Linear(input_dim, input_dim)
def forward(self, user_features, item_features):
combined = user_features + item_features
return self.fc(combined)
# 定义推荐系统模型
class EAMRModel(nn.Module):
def __init__(self, user_input_dim, item_input_dim, output_dim):
super(EAMRModel, self).__init__()
print(f"user_input_dim: {user_input_dim}, item_input_dim: {item_input_dim}")
self.attention_layer = MultiModalAttention(user_input_dim + item_input_dim, output_dim)
self.neighborhood_layer = NeighborhoodAwareLayer(output_dim)
def forward(self, user_features, item_features):
combined_features = torch.cat((user_features, item_features), dim=1)
attention_output = self.attention_layer(combined_features)
output = self.neighborhood_layer(user_features, attention_output)
return output
# 训练模型
def train_model(model, data_loader, epochs=10):
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(epochs):
for user_features, item_features, ratings in data_loader:
optimizer.zero_grad()
outputs = model(user_features, item_features)
loss = criterion(outputs.squeeze(), ratings)
loss.backward()
optimizer.step()
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
# 主程序
if __name__ == "__main__":
# 加载数据集
movies_df = pd.read_table('movie_titles.txt', encoding='ISO-8859-1', sep=',', header=None, on_bad_lines='skip') # 电影数据(包括电影ID和标题)
ratings = pd.read_excel('movielens.xlsx') # 评分数据(包括用户ID、电影ID和评分)
movies_df.columns = ["movie_id", "time", 'title']
# 创建用户和电影特征(这里简单使用用户ID和电影ID作为特征)
num_users = ratings['user_id'].nunique()
num_movies = ratings['movie_id'].nunique()
user_features = pd.get_dummies(ratings['user_id']).values # One-hot编码用户特征
item_features = pd.get_dummies(ratings['movie_id']).values # One-hot编码电影特征
# 划分训练集和测试集
train_ratings, test_ratings = train_test_split(ratings, test_size=0.2)
train_dataset = MovieLensDataset(train_ratings, user_features, item_features)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
model = EAMRModel(user_input_dim=user_features.shape[1], item_input_dim=item_features.shape[1], output_dim=1)
train_model(model, train_loader)
```