天地醒转 2025-01-05 20:13 采纳率: 44.4%
浏览 53
已结题

模型运行报错,runtime error

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)


```

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-01-05 20:15
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    从错误信息 RuntimeError: mat1 and mat2 shapes cannot be multiplied (64x943 and 1x1) 可以看出,问题出在矩阵乘法的维度不匹配上。具体来说,MultiModalAttention 层中的 nn.MultiheadAttention 期望输入的形状是 [seq_len, batch_size, embed_dim],而当前的输入形状是 [batch_size, input_dim]

    我们需要调整 MultiModalAttention 层的输入形状,使其符合 nn.MultiheadAttention 的要求。以下是详细的解决方案:

    1. 调整 MultiModalAttention 层的输入形状

      • 将输入形状从 [batch_size, input_dim] 调整为 [input_dim, batch_size]
      • 使用 permute 方法来调整形状。
    2. 调整 forward 方法中的 combined_features 形状

      • 确保 combined_features 的形状与 nn.MultiheadAttention 的期望形状一致。

    以下是修改后的代码:

    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):
            # 调整输入形状
            x = x.permute(1, 0, 2)
            attn_output, _ = self.attention(x, x, x)
            attn_output = attn_output.permute(1, 0, 2)
            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)
    

    通过上述修改,我们确保了 MultiModalAttention 层的输入形状符合 nn.MultiheadAttention 的要求,并且解决了矩阵乘法的维度不匹配问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 1月13日
  • 已采纳回答 1月5日
  • 创建了问题 1月5日