推荐系统的利弊

这一部分主要是关于开发者本身。(笔者个人观点:尽管有法律的约束,但是我个人认为法律约束只是界定了人类社会行为的道德下限,开发团队也应该有自己的道德约束)。尽管推荐系统对一些企业来说利润丰厚,但也存在使人们和社会状况变差的用例。在使用推荐系统或其他学习算法时,应致力于让社会和人们受益,避免造成伤害。

设计选择

在设计推荐系统时,从设定目标到决定推荐内容都有多种选择。例如,二元标签可依据用户是否参与、点击或明确喜欢某项目来设定;可以推荐用户最可能评五星的电影、最可能购买的产品等。推荐系统还可用于决定向用户展示的广告,许多公司会展示最可能被点击且广告客户出价高的广告,因为这关乎公司的收入。

存在的问题

  • 利润最大化与用户体验冲突:许多网站为实现利润最大化,不展示最相关或用户最可能购买的产品,而是展示利润最高的产品。从公司角度看,追求利润最大化有其合理性,但从用户角度,网站若能透明告知推荐标准(是追求利润还是提供有用内容)会更好。
  • 广告业务的两面性:广告业既能助力优秀、富有成效的企业(如旅游行业中,好的旅游公司因能提供优质服务而更盈利,进而能支付更高广告费用,吸引更多用户,形成良性循环),也可能成为有害业务(如发薪日贷款行业,高利率剥削低收入个人,善于剥削客户的公司更盈利,能支付更高广告费用获取更多流量,形成剥削更多人的恶性循环,这与社会利益相悖)的放大器。虽然可以拒绝展示剥削性企业的广告,但定义哪些企业属于剥削性企业存在困难。
  • 用户参与度与不良内容:为最大化用户参与度(如用户在网站上观看视频或在社交媒体上花费的时间),一些大型社交媒体和视频分享网站会放大阴谋论、仇恨和毒性内容,因为这些内容吸引力高。虽然可以过滤有问题的内容(如仇恨言论、欺诈骗局等),但明确过滤内容的定义也很棘手。
  • 推荐标准的透明度:当用户访问网站时,很多用户没意识到有些网站在推荐内容时更注重利润最大化,而非用户对媒体项目的使用乐趣。鼓励公司对用户公开推荐标准,因为这能增加信任,使系统为社会带来更多益处。

笔者注

推荐系统是强大且有利可图的技术,但存在太多问题用例,我自己遇到的就有大数据杀熟,假消息无法辨认(爬取数据的数据源本身就有问题),幻觉消息需要分辨(AI生成的信息xjb扩散思维,比如生成了历史中根本不曾存在的事件)等等。若开发者使用推荐技术或其他机器学习技术构建系统,不仅要考虑其带来的好处,还要考虑可能的危害。开发之前需要有一个基准,邀请不同观点进行讨论和辩论,做那些真正能让社会变得更好的事情。用AI创作者需要非常谨慎,使用者本人一定需要知道生成的东西是对的还是错的,不然累积起来的问题将会是非常可怕的错误。

简单的内容过滤系统

tensorflow代码

import tensorflow as tf
from tensorflow.keras import layers, models
import numpy as np
from sklearn.model_selection import train_test_split
import pandas as pd

# 模拟生成数据
# 假设我们有 100 个用户,每个用户有 5 个特征
num_users = 100
user_features = np.random.rand(num_users, 5).astype(np.float32)

# 假设我们有 200 部电影,每部电影有 6 个特征
num_movies = 200
movie_features = np.random.rand(num_movies, 6).astype(np.float32)

# 生成用户对电影的评分,范围从 1 到 5
ratings = np.random.randint(1, 6, size=(num_users, num_movies)).astype(np.float32)

# 将数据转换为适合训练的格式
user_indices = []
movie_indices = []
rating_values = []

for user_id in range(num_users):
    for movie_id in range(num_movies):
        user_indices.append(user_id)
        movie_indices.append(movie_id)
        rating_values.append(ratings[user_id, movie_id])

user_indices = np.array(user_indices)
movie_indices = np.array(movie_indices)
rating_values = np.array(rating_values)

# 划分训练集和测试集
X_user_train, X_user_test, X_movie_train, X_movie_test, y_train, y_test = train_test_split(
    user_indices, movie_indices, rating_values, test_size=0.2, random_state=42
)

# 构建用户网络
user_input = layers.Input(shape=(1,))
user_embedding = layers.Embedding(input_dim=num_users, output_dim=16)(user_input)
user_flatten = layers.Flatten()(user_embedding)
user_dense1 = layers.Dense(32, activation='relu')(user_flatten)
user_dense2 = layers.Dense(16, activation='relu')(user_dense1)

# 构建电影网络
movie_input = layers.Input(shape=(1,))
movie_embedding = layers.Embedding(input_dim=num_movies, output_dim=16)(movie_input)
movie_flatten = layers.Flatten()(movie_embedding)
movie_dense1 = layers.Dense(32, activation='relu')(movie_flatten)
movie_dense2 = layers.Dense(16, activation='relu')(movie_dense1)

# 合并用户和电影特征
concat_layer = layers.Concatenate()([user_dense2, movie_dense2])
output_layer = layers.Dense(1, activation='linear')(concat_layer)

# 构建模型
model = models.Model(inputs=[user_input, movie_input], outputs=output_layer)

# 编译模型
model.compile(optimizer='adam', loss='mse', metrics=['mae'])

# 训练模型
model.fit(
    [X_user_train, X_movie_train],
    y_train,
    epochs=10,
    batch_size=32,
    validation_split=0.1
)

# 评估模型
test_loss, test_mae = model.evaluate([X_user_test, X_movie_test], y_test)
print(f"Test Loss: {test_loss}, Test MAE: {test_mae}")

# 进行预测
sample_user_id = 0
movie_ids_to_predict = np.arange(num_movies)
user_input_for_prediction = np.full((num_movies,), sample_user_id)
predictions = model.predict([user_input_for_prediction, movie_ids_to_predict])
print(f"用户 {sample_user_id} 对各电影的预测评分: {predictions.flatten()}")
    

代码解释

在前面给出的代码里,“过滤” 这一概念没有以显式形式呈现,但其实内容过滤的思想是融入在模型构建和预测过程中的。

内容过滤的隐含体现

1. 特征提取与筛选

在代码里构建用户网络和电影网络时,每个网络都包含了多个全连接层(密集层)。这些全连接层的作用是从用户特征和电影特征里提取关键信息,进而实现对特征的筛选与过滤,筛选的过程中是算法进行的。

  • 用户网络
user_input = layers.Input(shape=(1,))
user_embedding = layers.Embedding(input_dim=num_users, output_dim=16)(user_input)
user_flatten = layers.Flatten()(user_embedding)
user_dense1 = layers.Dense(32, activation='relu')(user_flatten)
user_dense2 = layers.Dense(16, activation='relu')(user_dense1)

这里,输入的是用户 ID,通过嵌入层将其转化为 16 维的向量,接着经过两个全连接层。每一层都会对输入信息进行处理,只保留与预测评分相关的关键信息,过滤掉那些无关紧要的信息。

  • 电影网络
movie_input = layers.Input(shape=(1,))
movie_embedding = layers.Embedding(input_dim=num_movies, output_dim=16)(movie_input)
movie_flatten = layers.Flatten()(movie_embedding)
movie_dense1 = layers.Dense(32, activation='relu')(movie_flatten)
movie_dense2 = layers.Dense(16, activation='relu')(movie_dense1)

同理,电影网络也是对电影 ID 进行处理,提取出与电影相关的关键特征,过滤掉冗余信息。

2. 预测过程中的过滤

在预测阶段,模型会依据学习到的特征表示来预测用户对电影的评分。模型只会输出那些与用户偏好相关的预测结果,从而实现对内容的过滤。

sample_user_id = 0
movie_ids_to_predict = np.arange(num_movies)
user_input_for_prediction = np.full((num_movies,), sample_user_id)
predictions = model.predict([user_input_for_prediction, movie_ids_to_predict])

在预测时,模型会根据用户的特征和电影的特征,预测该用户对所有电影的评分。对于那些预测评分较低的电影,就可以理解为是被过滤掉的内容,因为它们不太符合用户的偏好。

显式过滤的实现思路

如果你希望实现显式的内容过滤,可以在预测结果之后添加额外的逻辑。例如,只推荐预测评分高于某个阈值的电影:

threshold = 3
recommended_movies = []
for movie_id, prediction in zip(movie_ids_to_predict, predictions.flatten()):
    if prediction >= threshold:
        recommended_movies.append(movie_id)
print(f"推荐给用户 {sample_user_id} 的电影 ID: {recommended_movies}")

自然,也可以自定义其它条件判断,这个读者自己去尝试。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐