当前位置:   article > 正文

简单实现——多模态推荐和相似推荐(数据和代码)

多模态推荐

在很多领域都用到了多模态推荐,但是很多时候构建多模态模型所需要的数据量是非常大的,所以在实现多模态推荐前,我们可以使用相似推荐来过渡。

多模态是包括文本,音频,图片,视频等模态的。

这里我做的是将文本和图片模态做一个简单融合。

根据难度,从相似推荐开始,再到多模态推荐。

以下是大致的流程:

ba67eef0e7e145c1b0f339a563e52f39.png

在这里是我自己制作的电商数据,包括物品的文本描述,与物品的图片,还有推荐算法的基本要素,即用户对物品的交互,其中包括购买,加入购物车,还有收藏,喜欢。

以下是物品数据:

337b0e77c7d446679b4589d5727c487c.png

以下是用户交互数据:

其中ACTION = ( (0, '点击'), (1, '收藏'), (2, '加入购物车'), (3, '购买'), )

0d4bb7517d95439bb3fe35eee3d15aec.jpg

相似推荐,考虑的是物品与物品之间的相似,所以要对物品文本描述和物品图片做相似度处理。

每一个单独的物品,都有文本描述和物品图片。

图片通过自己训练的神经网络模型,去除最后一层,即得到提取的特征值数据。

文本描述同理,但是这里采用的是借用别人的。

融合之后,我们通过对每一个物品做相似度处理,则得到一个相似度的值,通过相似度值作为评分,来作为物品对物品推荐。

  1. import numpy as np
  2. from sklearn.feature_extraction.text import TfidfVectorizer
  3. from tensorflow.keras.preprocessing import image
  4. from tensorflow.keras.models import load_model
  5. from tensorflow.keras.models import Model
  6. from tensorflow.keras.layers import Input, Dense, Flatten
  7. from sklearn.preprocessing import StandardScaler,MinMaxScaler
  8. from sklearn.metrics.pairwise import cosine_similarity
  9. import pandas as pd
  10. import os
  11. import random
  12. cnn = load_model("K:/photo/cnn_model.h5")
  13. # CSV文件列:'item_id', 'description', 'image_path','tag'
  14. data = pd.read_csv('K:/下载/product_data.csv', encoding='utf-8', sep=',')
  15. input_layer = cnn.input
  16. # 获取最后一个全连接层之前的层,作为特征层
  17. # 最后一个全连接层之前有一个Flatten层
  18. # 找到正确的特征层
  19. for layer in cnn.layers:
  20. if isinstance(layer, Flatten):
  21. feature_layer = layer.output
  22. break
  23. # 构建特征提取器模型
  24. cnn = Model(input_layer, feature_layer)
  25. # 文本特征提取
  26. tfidf_vectorizer = TfidfVectorizer()
  27. text_features = tfidf_vectorizer.fit_transform(data['description'])
  28. address = r'K:/django/Item/app01'
  29. # 图像特征提取
  30. image_features = []
  31. #图片提取特征值
  32. for image_path in data['image_path']:
  33. img = image.load_img(address+image_path, target_size=(50, 50))
  34. img_data = image.img_to_array(img)
  35. img_data = np.expand_dims(img_data, axis=0)
  36. features = cnn.predict(img_data)
  37. image_features.append(features.flatten())
  38. #转换
  39. image_features = np.array(image_features)
  40. #标准化
  41. scaler_text = StandardScaler()#标准差标准化
  42. # scaler_text = MinMaxScaler()#最大最小标准化
  43. text_features_scaled = scaler_text.fit_transform(text_features.toarray())
  44. # text_features_scaled = text_features.toarray()#没有标准化
  45. scaler_image = StandardScaler()#标准差标准化
  46. # scaler_image = MinMaxScaler()#最大最小标准化
  47. image_features_scaled = scaler_image.fit_transform(image_features)
  48. # print(text_features)
  49. # print(image_features)
  50. # text_features_scaled = image_features#没有标准化
  51. # 分配权重,因为两者权重问题,所以在处理时候不应该标准差标准化,应该最大最小标准化
  52. text_weight = 0.3
  53. image_weight = 0.7
  54. random.seed()
  55. # 加权特征融合
  56. weighted_text_features = text_features_scaled * text_weight
  57. weighted_image_features = image_features_scaled * image_weight
  58. # 合并加权后的特征
  59. combined_features_weighted = np.hstack((weighted_text_features, weighted_image_features))
  60. # 计算余弦相似度
  61. similarity_matrix = cosine_similarity(combined_features_weighted)
  62. # print(similarity_matrix)
  63. # 用户的历史交互列表用户喜欢的商品ID
  64. # 推荐函数
  65. def recommend_items(user_history, similarity_matrix, item_ids):
  66. # 确保 user_history 中的项目都在 item_ids 中
  67. user_history = [item for item in user_history if item in item_ids]
  68. # print(user_history)
  69. # 获取用户历史项目的索引
  70. user_item_indices = [item_ids.index(item) for item in user_history]
  71. # 确保我们找到了所有用户历史项目的索引
  72. if len(user_item_indices) != len(user_history):
  73. raise ValueError("Some items in user history are not in the item_ids list.")
  74. # 获取用户历史项目的相似度行
  75. user_similarities = similarity_matrix[user_item_indices, :]
  76. # 初始化推荐项目得分字典
  77. item_scores = {item_id: 0 for item_id in item_ids}
  78. # 累加用户历史项目与其他项目的相似度
  79. for idx, sim_row in zip(user_item_indices, user_similarities):
  80. # 累加除了用户已经交互过的项目之外的相似度
  81. for jdx, score in enumerate(sim_row):
  82. item_id = item_ids[jdx]
  83. item_scores[item_id] += score
  84. # 根据得分推荐项目
  85. sorted_scores = sorted(item_scores.items(), key=lambda x: x[1], reverse=True)
  86. # 指定数量的推荐
  87. return sorted_scores
  88. df = pd.DataFrame(columns=['product_mian', 'product_id', 'score'])
  89. for i in list(data["item_id"]):
  90. product = []
  91. product.append(i)
  92. # 用商品来推荐商品
  93. # 输出推荐结果
  94. recommendations = recommend_items(product, similarity_matrix, data["item_id"].tolist())
  95. for item_id, score in recommendations:
  96. df = df.append(
  97. {'product_main': i, 'product_id': str(item_id), 'score': score}, ignore_index=True)
  98. # 将新的DataFrame保存到CSV文件
  99. df.to_csv('product_recommendations.csv', index=False, encoding='utf-8', sep=',')

bbdb1715d6e147078b44f79964d438a5.png

其实可以发现物品之间相似度是有负数的,这就说明物品与物品之间存在负相关。

通过这两个模态融合做一个模型,就得到了相似推荐。

这种推荐模式,是基于物品图片和物品文本来推荐的,与用户交互无关,但后面我们会加入进去融合起来。

———————————————————————————————————————————

相似推荐之后就是融合行为进去,做成多模态推荐算法。

处理用户行为权重

ACTION = (
    (0, '点击'),
    (1, '收藏'),
    (2, '加入购物车'),
    (3, '购买'),
)

分别给不同行为不同的权重。

  1. import pandas as pd
  2. # 读取数据
  3. df = pd.read_csv('K:/下载/user_actions.csv')
  4. # 定义行为权重
  5. action_weights = {0: 1, 1: 2, 2: 3, 3: 5}
  6. # 转换action字段为权重
  7. df['weight'] = df['action'].map(action_weights)
  8. # 按照用户ID和商品ID对数据进行分组,并计算每个组的权重总和
  9. grouped = df.groupby(['user_id', 'product_id'])['weight'].sum().reset_index()
  10. # 将结果重命名为更有意义的列名
  11. grouped = grouped.rename(columns={'weight': 'total_weight'})
  12. # 写入CSV文件
  13. grouped.to_csv('user_product_weights.csv', index=False)
  14. print(grouped)

2d6300f7afe14bd6bf18dc4036bb993e.png

我们从用户喜欢的物品之中,计算所有之外的物品的相似度,然后实现对用户所有的交互的物品对未知的物品的可能好感,这里是不包含用户行为的。

  1. import numpy as np
  2. from sklearn.feature_extraction.text import TfidfVectorizer
  3. from tensorflow.keras.preprocessing import image
  4. from tensorflow.keras.models import load_model
  5. from tensorflow.keras.models import Model
  6. from tensorflow.keras.layers import Input, Dense, Flatten
  7. from sklearn.preprocessing import StandardScaler,MinMaxScaler
  8. from sklearn.metrics.pairwise import cosine_similarity
  9. import pandas as pd
  10. import os
  11. import random
  12. cnn = load_model("K:/photo/cnn_model.h5")
  13. # CSV文件列:'item_id', 'description', 'image_path','tag'
  14. data = pd.read_csv('K:/下载/product_data.csv', encoding='utf-8', sep=',')
  15. input_layer = cnn.input
  16. # 获取最后一个全连接层之前的层,作为特征层
  17. # 最后一个全连接层之前有一个Flatten层
  18. # 找到正确的特征层
  19. for layer in cnn.layers:
  20. if isinstance(layer, Flatten):
  21. feature_layer = layer.output
  22. break
  23. # 构建特征提取器模型
  24. cnn = Model(input_layer, feature_layer)
  25. # 文本特征提取
  26. tfidf_vectorizer = TfidfVectorizer()
  27. text_features = tfidf_vectorizer.fit_transform(data['description'])
  28. address = r'K:/django/Item/app01'
  29. # 图像特征提取
  30. image_features = []
  31. #图片提取特征值
  32. for image_path in data['image_path']:
  33. img = image.load_img(address+image_path, target_size=(50, 50))
  34. img_data = image.img_to_array(img)
  35. img_data = np.expand_dims(img_data, axis=0)
  36. features = cnn.predict(img_data)
  37. image_features.append(features.flatten())
  38. #转换
  39. image_features = np.array(image_features)
  40. #标准化
  41. scaler_text = StandardScaler()#标准差标准化
  42. # scaler_text = MinMaxScaler()#最大最小标准化
  43. text_features_scaled = scaler_text.fit_transform(text_features.toarray())
  44. # text_features_scaled = text_features.toarray()#没有标准化
  45. scaler_image = StandardScaler()#标准差标准化
  46. # scaler_image = MinMaxScaler()#最大最小标准化
  47. image_features_scaled = scaler_image.fit_transform(image_features)
  48. # print(text_features)
  49. # print(image_features)
  50. # text_features_scaled = image_features#没有标准化
  51. # 分配权重,因为两者权重问题,所以在处理时候不应该标准差标准化,应该最大最小标准化
  52. text_weight = 0.3
  53. image_weight = 0.7
  54. random.seed()
  55. # 加权特征融合
  56. weighted_text_features = text_features_scaled * text_weight
  57. weighted_image_features = image_features_scaled * image_weight
  58. # 合并加权后的特征
  59. combined_features_weighted = np.hstack((weighted_text_features, weighted_image_features))
  60. # 计算余弦相似度
  61. similarity_matrix = cosine_similarity(combined_features_weighted)
  62. # print(similarity_matrix)
  63. # 用户的历史交互列表用户喜欢的商品ID
  64. # 推荐函数
  65. def recommend_items(user_history, similarity_matrix, item_ids):
  66. # 确保 user_history 中的项目都在 item_ids 中
  67. user_history = [item for item in user_history if item in item_ids]
  68. # print(user_history)
  69. # 获取用户历史项目的索引
  70. user_item_indices = [item_ids.index(item) for item in user_history]
  71. # print(user_item_indices)
  72. # print(item_ids)
  73. # 确保我们找到了所有用户历史项目的索引
  74. if len(user_item_indices) != len(user_history):
  75. raise ValueError("Some items in user history are not in the item_ids list.")
  76. # 获取用户历史项目的相似度行
  77. user_similarities = similarity_matrix[user_item_indices, :]
  78. # 初始化推荐项目得分字典
  79. item_scores = {item_id: 0 for item_id in item_ids}
  80. # 累加用户历史项目与其他项目的相似度
  81. for idx, sim_row in zip(user_item_indices, user_similarities):
  82. # 累加除了用户已经交互过的项目之外的相似度
  83. for jdx, score in enumerate(sim_row):
  84. item_id = item_ids[jdx]
  85. item_scores[item_id] += score
  86. # 根据得分推荐项目
  87. sorted_scores = sorted(item_scores.items(), key=lambda x: x[1], reverse=True)
  88. # 指定数量的推荐
  89. return sorted_scores
  90. df = pd.read_csv('K:/下载/user_actions.csv', encoding='utf-8', sep=',')
  91. user_product_mapping = df.groupby('user_id')['product_id'].apply(lambda x: list(set(x))).reset_index(name='product_id')
  92. df = pd.DataFrame(columns=['user_id', 'product_id', 'score'])
  93. for i in range(len(user_product_mapping)):
  94. # print(user_product_mapping.iloc[i])
  95. # print(user_product_mapping.iloc[i]['product_id'])
  96. # 打乱列表顺序,确保随机性
  97. list_items = user_product_mapping.iloc[i]['product_id']
  98. user_history = user_product_mapping.iloc[i]['product_id']
  99. user_recommendations = recommend_items(user_history, similarity_matrix, data["item_id"].tolist())
  100. # 将推荐的项目ID和得分分离
  101. user_id = user_product_mapping.iloc[i]["user_id"]
  102. recommended_items = [item_id for item_id, score in user_recommendations]
  103. for item_id, score in user_recommendations:
  104. df = df.append(
  105. {'user_id': user_id, 'product_id': str(item_id), 'score': score}, ignore_index=True)
  106. # 将新的DataFrame保存到CSV文件
  107. df.to_csv('user_recommendations.csv', index=False, encoding='utf-8', sep=',')

 如图所示:

2e0f6d15f42c47ceb32928a7e96740de.png

我们要将用户行为加入进去,简单的融合方法就是得出的数值相乘:

  1. import pandas as pd
  2. # 第一个CSV文件
  3. df1 = pd.read_csv('user_product_weights.csv')
  4. # 第二个CSV文件
  5. df2 = pd.read_csv('user_recommendations.csv')
  6. # 基于user_id和product_id合并两个DataFrame
  7. merged_df = pd.merge( df1,df2,on=['user_id', 'product_id'], how='outer')
  8. # 填充缺失值,例如用0替换NaN
  9. merged_df.fillna(0, inplace=True)
  10. merged_df['weighted_score'] = merged_df['score'] * merged_df['total_weight']
  11. # 将结果保存到新的CSV文件
  12. merged_df.to_csv('merged.csv', index=False)

cb8b38e7c06644c3a8bf556800bf2fdb.png

我将全部的一些代码和训练模型打包,放到同站免费下载。

但是要对地址做一些处理。

文件参考如下:

79851bf19bce4045894529f906dca1c8.png

资源:https://download.csdn.net/download/weixin_52810349/89511066 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/998405
推荐阅读
相关标签
  

闽ICP备14008679号