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

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

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

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

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

以下是大致的流程:

ba67eef0e7e145c1b0f339a563e52f39.png

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

以下是物品数据:

337b0e77c7d446679b4589d5727c487c.png

以下是用户交互数据:

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

0d4bb7517d95439bb3fe35eee3d15aec.jpg

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

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

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

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

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

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import load_model
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Flatten
from sklearn.preprocessing import StandardScaler,MinMaxScaler
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd
import os
import random
cnn = load_model("K:/photo/cnn_model.h5")
# CSV文件列:'item_id', 'description', 'image_path','tag'
data = pd.read_csv('K:/下载/product_data.csv', encoding='utf-8', sep=',')

input_layer = cnn.input
# 获取最后一个全连接层之前的层,作为特征层
# 最后一个全连接层之前有一个Flatten层
# 找到正确的特征层
for layer in cnn.layers:
    if isinstance(layer, Flatten):
        feature_layer = layer.output
        break

    # 构建特征提取器模型
cnn = Model(input_layer, feature_layer)
# 文本特征提取
tfidf_vectorizer = TfidfVectorizer()
text_features = tfidf_vectorizer.fit_transform(data['description'])
address = r'K:/django/Item/app01'
# 图像特征提取
image_features = []

#图片提取特征值
for image_path in data['image_path']:
    img = image.load_img(address+image_path, target_size=(50, 50))
    img_data = image.img_to_array(img)
    img_data = np.expand_dims(img_data, axis=0)
    features = cnn.predict(img_data)
    image_features.append(features.flatten())
#转换
image_features = np.array(image_features)

#标准化
scaler_text = StandardScaler()#标准差标准化
# scaler_text = MinMaxScaler()#最大最小标准化
text_features_scaled = scaler_text.fit_transform(text_features.toarray())
# text_features_scaled = text_features.toarray()#没有标准化
scaler_image = StandardScaler()#标准差标准化
# scaler_image = MinMaxScaler()#最大最小标准化
image_features_scaled = scaler_image.fit_transform(image_features)
# print(text_features)
# print(image_features)
# text_features_scaled = image_features#没有标准化
# 分配权重,因为两者权重问题,所以在处理时候不应该标准差标准化,应该最大最小标准化
text_weight = 0.3
image_weight = 0.7
random.seed()

# 加权特征融合
weighted_text_features = text_features_scaled * text_weight
weighted_image_features = image_features_scaled * image_weight

# 合并加权后的特征
combined_features_weighted = np.hstack((weighted_text_features, weighted_image_features))

# 计算余弦相似度
similarity_matrix = cosine_similarity(combined_features_weighted)
# print(similarity_matrix)
# 用户的历史交互列表用户喜欢的商品ID


# 推荐函数
def recommend_items(user_history, similarity_matrix, item_ids):
    # 确保 user_history 中的项目都在 item_ids 中
    user_history = [item for item in user_history if item in item_ids]
    # print(user_history)
    # 获取用户历史项目的索引
    user_item_indices = [item_ids.index(item) for item in user_history]
    # 确保我们找到了所有用户历史项目的索引
    if len(user_item_indices) != len(user_history):
        raise ValueError("Some items in user history are not in the item_ids list.")

        # 获取用户历史项目的相似度行
    user_similarities = similarity_matrix[user_item_indices, :]

    # 初始化推荐项目得分字典
    item_scores = {item_id: 0 for item_id in item_ids}

    # 累加用户历史项目与其他项目的相似度
    for idx, sim_row in zip(user_item_indices, user_similarities):
        # 累加除了用户已经交互过的项目之外的相似度
        for jdx, score in enumerate(sim_row):
                item_id = item_ids[jdx]
                item_scores[item_id] += score

                # 根据得分推荐项目
    sorted_scores = sorted(item_scores.items(), key=lambda x: x[1], reverse=True)

    # 指定数量的推荐
    return sorted_scores


df = pd.DataFrame(columns=['product_mian', 'product_id', 'score'])
for i in list(data["item_id"]):
    product = []
    product.append(i)
    # 用商品来推荐商品
    # 输出推荐结果
    recommendations = recommend_items(product, similarity_matrix, data["item_id"].tolist())
    for item_id, score in recommendations:
        df = df.append(
            {'product_main': i, 'product_id': str(item_id), 'score': score}, ignore_index=True)
        # 将新的DataFrame保存到CSV文件
df.to_csv('product_recommendations.csv', index=False, encoding='utf-8', sep=',')

bbdb1715d6e147078b44f79964d438a5.png

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

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

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

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

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

处理用户行为权重

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

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

import pandas as pd

# 读取数据
df = pd.read_csv('K:/下载/user_actions.csv')

# 定义行为权重
action_weights = {0: 1, 1: 2, 2: 3, 3: 5}

# 转换action字段为权重
df['weight'] = df['action'].map(action_weights)

# 按照用户ID和商品ID对数据进行分组,并计算每个组的权重总和
grouped = df.groupby(['user_id', 'product_id'])['weight'].sum().reset_index()

# 将结果重命名为更有意义的列名
grouped = grouped.rename(columns={'weight': 'total_weight'})

# 写入CSV文件
grouped.to_csv('user_product_weights.csv', index=False)

print(grouped)

2d6300f7afe14bd6bf18dc4036bb993e.png

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

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from tensorflow.keras.preprocessing import image
from tensorflow.keras.models import load_model
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Flatten
from sklearn.preprocessing import StandardScaler,MinMaxScaler
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd
import os
import random
cnn = load_model("K:/photo/cnn_model.h5")
# CSV文件列:'item_id', 'description', 'image_path','tag'
data = pd.read_csv('K:/下载/product_data.csv', encoding='utf-8', sep=',')

input_layer = cnn.input
# 获取最后一个全连接层之前的层,作为特征层
# 最后一个全连接层之前有一个Flatten层
# 找到正确的特征层
for layer in cnn.layers:
    if isinstance(layer, Flatten):
        feature_layer = layer.output
        break

    # 构建特征提取器模型
cnn = Model(input_layer, feature_layer)
# 文本特征提取
tfidf_vectorizer = TfidfVectorizer()
text_features = tfidf_vectorizer.fit_transform(data['description'])
address = r'K:/django/Item/app01'
# 图像特征提取
image_features = []

#图片提取特征值
for image_path in data['image_path']:
    img = image.load_img(address+image_path, target_size=(50, 50))
    img_data = image.img_to_array(img)
    img_data = np.expand_dims(img_data, axis=0)
    features = cnn.predict(img_data)
    image_features.append(features.flatten())
#转换
image_features = np.array(image_features)

#标准化
scaler_text = StandardScaler()#标准差标准化
# scaler_text = MinMaxScaler()#最大最小标准化
text_features_scaled = scaler_text.fit_transform(text_features.toarray())
# text_features_scaled = text_features.toarray()#没有标准化
scaler_image = StandardScaler()#标准差标准化
# scaler_image = MinMaxScaler()#最大最小标准化
image_features_scaled = scaler_image.fit_transform(image_features)
# print(text_features)
# print(image_features)
# text_features_scaled = image_features#没有标准化
# 分配权重,因为两者权重问题,所以在处理时候不应该标准差标准化,应该最大最小标准化
text_weight = 0.3
image_weight = 0.7
random.seed()

# 加权特征融合
weighted_text_features = text_features_scaled * text_weight
weighted_image_features = image_features_scaled * image_weight

# 合并加权后的特征
combined_features_weighted = np.hstack((weighted_text_features, weighted_image_features))

# 计算余弦相似度
similarity_matrix = cosine_similarity(combined_features_weighted)
# print(similarity_matrix)
# 用户的历史交互列表用户喜欢的商品ID


# 推荐函数
def recommend_items(user_history, similarity_matrix, item_ids):
    # 确保 user_history 中的项目都在 item_ids 中
    user_history = [item for item in user_history if item in item_ids]
    # print(user_history)
    # 获取用户历史项目的索引
    user_item_indices = [item_ids.index(item) for item in user_history]
    # print(user_item_indices)
    # print(item_ids)
    # 确保我们找到了所有用户历史项目的索引
    if len(user_item_indices) != len(user_history):
        raise ValueError("Some items in user history are not in the item_ids list.")

        # 获取用户历史项目的相似度行
    user_similarities = similarity_matrix[user_item_indices, :]

    # 初始化推荐项目得分字典
    item_scores = {item_id: 0 for item_id in item_ids}

    # 累加用户历史项目与其他项目的相似度
    for idx, sim_row in zip(user_item_indices, user_similarities):
        # 累加除了用户已经交互过的项目之外的相似度
        for jdx, score in enumerate(sim_row):
                item_id = item_ids[jdx]
                item_scores[item_id] += score

                # 根据得分推荐项目
    sorted_scores = sorted(item_scores.items(), key=lambda x: x[1], reverse=True)

    # 指定数量的推荐
    return sorted_scores


df = pd.read_csv('K:/下载/user_actions.csv', encoding='utf-8', sep=',')
user_product_mapping = df.groupby('user_id')['product_id'].apply(lambda x: list(set(x))).reset_index(name='product_id')
df = pd.DataFrame(columns=['user_id', 'product_id', 'score'])
for i in range(len(user_product_mapping)):
    # print(user_product_mapping.iloc[i])
    # print(user_product_mapping.iloc[i]['product_id'])
    # 打乱列表顺序,确保随机性
    list_items = user_product_mapping.iloc[i]['product_id']
    user_history = user_product_mapping.iloc[i]['product_id']
    user_recommendations = recommend_items(user_history, similarity_matrix, data["item_id"].tolist())
    # 将推荐的项目ID和得分分离
    user_id = user_product_mapping.iloc[i]["user_id"]
    recommended_items = [item_id for item_id, score in user_recommendations]
    for item_id, score in user_recommendations:
        df = df.append(
            {'user_id': user_id, 'product_id': str(item_id), 'score': score}, ignore_index=True)
        # 将新的DataFrame保存到CSV文件
df.to_csv('user_recommendations.csv', index=False, encoding='utf-8', sep=',')

 如图所示:

2e0f6d15f42c47ceb32928a7e96740de.png

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

import pandas as pd

# 第一个CSV文件
df1 = pd.read_csv('user_product_weights.csv')

# 第二个CSV文件
df2 = pd.read_csv('user_recommendations.csv')

# 基于user_id和product_id合并两个DataFrame
merged_df = pd.merge( df1,df2,on=['user_id', 'product_id'], how='outer')
# 填充缺失值,例如用0替换NaN
merged_df.fillna(0, inplace=True)
merged_df['weighted_score'] = merged_df['score'] * merged_df['total_weight']
# 将结果保存到新的CSV文件
merged_df.to_csv('merged.csv', index=False)

cb8b38e7c06644c3a8bf556800bf2fdb.png

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

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

文件参考如下:

79851bf19bce4045894529f906dca1c8.png

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

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值