• 全部
...

个人技术总结——推荐算法

222200404刘嘉榕 2024-12-10 21:41:50

目录

  • 技术概述
  • 背景
  • 几种常见的推荐算法:
  • 1.协同过滤(Collaborative Filtering)
  • 2. 奇异值分解(Singular Value Decomposition,SVD)
  • 3. 基于内容的推荐(Content-based Recommendation)
  • 4. 混合推荐系统(Hybrid Recommendation Systems)
  • 5. 深度学习推荐模型
  • 技术详述
  • 通用操作
  • 基于用户的协同过滤(User-based Collaborative Filtering)
  • 数据处理
  • 寻找相似用户
  • 预测
  • 系统集成
  • 基于物品的协同过滤(Item-based Collaborative Filtering)
  • 数据处理
  • 寻找具有相似特征的物品推荐给用户
  • 改进: 调整后的余弦相似度
  • 深度学习推荐模型(推荐算法和宽广神经网络模型结合)
  • 模型
  • wide模型
  • deep模型
  • Wide部分和Deep部分通过加权的方式合并在一起。
  • 数据预处理
  • 训练
  • 效果
  • 遇到的问题和解决方案
  • 问题1:数据稀疏性问题
  • 问题2:模型过拟合问题
  • 问题3:系统性能优化
  • 总结
  • 参考文献

技术概述

推荐算法技术用于分析用户行为和偏好,预测并推荐用户可能感兴趣的内容或产品。在电子商务、流媒体服务等需要个性化推荐的场景中尤为重要。学习该技术是为了提升用户体验和平台用户粘性。技术难点在于推荐的准确性和效率。

背景

随着技术的发展,推荐算法不断演进,从传统的协同过滤到基于内容的推荐,再到混合推荐系统和深度学习推荐模型,每种方法都有其独特的优势和应用场景。

几种常见的推荐算法:

1.协同过滤(Collaborative Filtering)

协同过滤是推荐系统中最经典的算法之一,它基于用户的历史行为(如评分、点击等)来进行推荐。协同过滤有两种主要实现方式:

  • 基于用户的协同过滤(User-based Collaborative Filtering):这种方法通过寻找与目标用户兴趣相似的其他用户,推荐这些用户喜欢的物品。它依赖于用户之间的相似度计算,通常使用余弦相似度或皮尔逊相关系数等方法。

  • 基于物品的协同过滤(Item-based Collaborative Filtering):这种方法通过计算物品之间的相似度,推荐与用户已评价的物品相似的其他物品。它通常比基于用户的方法更高效,因为物品的数量通常少于用户数量。

2. 奇异值分解(Singular Value Decomposition,SVD)

SVD是一种矩阵分解方法,用于将用户-物品评分矩阵分解为三个矩阵的乘积:U(用户特征矩阵)、Σ(奇异值矩阵)、V(物品特征矩阵)。通过对评分矩阵进行SVD分解,可以找到潜在的用户和物品特征,从而预测用户对物品的评分。SVD在处理大规模数据集时特别有效,因为它能降维并提取数据的潜在结构。

3. 基于内容的推荐(Content-based Recommendation)

基于内容的推荐算法侧重于分析物品的内容特征,如文本、图像或视频内容。这种方法通过匹配用户的历史偏好和物品的特征来生成推荐。它通常用于内容丰富的环境,如新闻文章、博客或视频。

4. 混合推荐系统(Hybrid Recommendation Systems)

混合推荐系统结合了多种推荐技术,以克服单一方法的局限性。例如,它可以结合协同过滤和基于内容的推荐,以提高推荐的准确性和多样性。混合系统可以利用不同算法的优势,提供更全面和个性化的推荐。

5. 深度学习推荐模型

随着深度学习技术的发展,基于神经网络的推荐模型越来越受到关注。这些模型可以自动学习用户和物品的复杂特征表示,并用于预测用户的行为。深度学习推荐模型在处理大规模数据集和复杂用户行为时表现出色。

推荐算法的选择和实现取决于具体的应用场景、数据可用性和业务目标。有效的推荐系统可以显著提升用户体验和平台的用户粘性。随着技术的不断进步,推荐算法将继续发展和优化,以满足日益增长的个性化需求。

技术详述

通用操作

img

基于用户的协同过滤(User-based Collaborative Filtering)

核心思想是找到与目标用户兴趣相似的其他用户,然后推荐那些相似用户喜欢而目标用户尚未接触的物品。

数据处理

为了确保推荐的相关
性,我对搜索词和地理位置进行了严格的限定,确保推荐的美食名称必须包含搜索词且在用户附近(这里我定义的是1.5km以内)。通过分析用户的点赞、点踩和搜索记录等行为,我们构造了每个商品的得分向量,其中点赞行为对商品得分的正面影响最大,点踩行为则产生负面影响,而搜索记录则提供了一个较小的正面影响。在关键词匹配中,我们使用Jaccard相似度来衡量搜索词与菜谱或美食名称的匹配度,以确保推荐结果的相关性。其中为了对外提供接口,统一使用一个函数,并使用isRecipe作为区分美食和菜谱。

在a阶段测试时,发现推荐速度太慢,于是进行了以下优化:

优化1:数据库结构设计:为关键词和描述建立索引提高查询速度。

优化2:数据库操作优化:使用连接池来避免频繁地打开和关闭数据库连接,通过重用现有的数据库连接来提高效率。同时,采用批量查询来减少数据库查询次数,优化数据获取过程。

优化2:缓存机制的应用:通过使用缓存保存用户的相关记录,便于下次快速使用,这不仅提高了系统的响应速度,也减轻了数据库的压力。

寻找相似用户

使用findksimilarusers函数通过计算用户之间的相似度,找出最相似的k个用户(邻居)。

在选择相似性度量时,可根据以下几点进行选择:

• 当数据受用户偏好/用户的不同评分尺度影响时,请使用皮尔逊相似度

• 如果数据稀疏,则使用余弦(许多额定值未定义)

• 如果数据不稀疏并且属性值的大小很重要,请使用欧几里得(Euclidean)。

• 建议使用调整后的余弦(Adjusted Cosine Similarity)进行基于商品的方法来调整用户偏好。

我在这里使用余弦相似性,其定义如下:

img

通过构造用户-商品得分矩阵并对矩阵计算余弦相似度得到最相似的k个用户(我设置4个)。

预测

使用这些相似的用户的对商品的评分数据来预测目标用户对未评分物品的评分或偏好:通过邻居平均值的偏差的加权平均值来计算,并将其添加到目标用户的平均评分中。 偏差用于调整用户相关的偏差。 出现用户偏差的原因是某些用户可能总是对所有项目给予高评分或低评分。

img

其中p(a,i)是目标用户a对商品i的预测,w(a,u)是用户a和u之间的相似度,K是和目标用户相似的K个用户。

系统集成

把推荐系统作为服务部署,使用flask应用提供API接口。

问题:在用户基数较大的应用程序中,基于用户的方法面临可扩展性问题,因为它们的复杂性随用户数量呈线性增长。基于商品的方法解决了这些可扩展性问题,因此有了基于商品相似性推荐项目。

基于物品的协同过滤(Item-based Collaborative Filtering)

基于物品的推荐算法主要依赖于物品的属性和特征,为用户推荐与他们之前喜欢的物品相似的新物品。

数据处理

采用与基于用户的协同过滤相似的处理方法,分析用户过去喜欢的物品的特征。

寻找具有相似特征的物品推荐给用户

使用余弦相似性度量来计算一对商品之间的相似度。 可以通过使用简单的加权平均值来预测目标用户a对目标商品i的评分:

img

函数findksimilaritems使用最近邻方法采用余弦相似性来找到k项最相似的商品i。

改进: 调整后的余弦相似度

使用基于商品的推荐系统方法的余弦相似性度量不考虑用户评分的偏差。 调整后的余弦相似度通过从每个共同评分对中减去各自用户的平均评分来抵消该缺点,并且被定义为如下

img

为了在Python中实现Adjusted Cosine相似度,我定义了一个名为computeAdjCosSim的简单函数,该函数返回调整后的余弦相似度矩阵,给出评分矩阵。函数findksimilaritems_adjcos和predic
t_itembased_adjcos利用调整后的余弦相似度来查找k个相似项并计算预测评分。

  1. def computeAdjCosSim(M):
  2. sim_matrix = np.zeros((M.shape[1], M.shape[1]))
  3. M_u = M.mean(axis=1) # mean
  4. for i in range(M.shape[1]):
  5. for j in range(M.shape[1]):
  6. if i == j:
  7. sim_matrix[i][j] = 1
  8. else:
  9. if i < j:
  10. sum_num = sum_den1 = sum_den2 = 0
  11. for k, row in M.loc[:, [i, j]].iterrows():
  12. if ((M.loc[k, i] != 0) & (M.loc[k, j] != 0)):
  13. num = (M[i][k] - M_u[k]) * (M[j][k] - M_u[k])
  14. den1 = (M[i][k] - M_u[k]) ** 2
  15. den2 = (M[j][k] - M_u[k]) ** 2
  16. sum_num = sum_num + num
  17. sum_den1 = sum_den1 + den1
  18. sum_den2 = sum_den2 + den2
  19. else:
  20. continue
  21. den = (sum_den1 ** 0.5) * (sum_den2 ** 0.5)
  22. if den != 0:
  23. sim_matrix[i][j] = sum_num / den
  24. else:
  25. sim_matrix[i][j] = 0
  26. else:
  27. sim_matrix[i][j] = sim_matrix[j][i]
  28. return pd.DataFrame(sim_matrix)
  1. def findksimilaritems_adjcos(item_id, ratings, k=4):
  2. sim_matrix = computeAdjCosSim(ratings)
  3. similarities = sim_matrix[item_id - 1].sort_values(ascending=False)
  4. indices = sim_matrix[item_id - 1].sort_values(ascending=False)[:k].index
  5. print('{0} most similar items for item {1}:\n'.format(k - 1, item_id))
  6. for i in range(0, len(indices)):
  7. if indices[i] + 1 == item_id:
  8. continue
  9. else:
  10. print('{0}: Item {1} :, with similarity of {2}'.format(i, indices[i] + 1, similarities[i]))
  11. return similarities, indices
  1. def predict_itembased_adjcos(user_id, ratings):
  2. prediction = 0
  3. for item_id in range(ratings.shape[1]):
  4. similarities, indices = findksimilaritems_adjcos(item_id, ratings)
  5. # similar users based on correlation coefficients
  6. sum_wt = np.sum(similarities) - 1
  7. product = 1
  8. wtd_sum = 0
  9. for i in range(0, len(indices)):
  10. if indices[i] + 1 == item_id:
  11. continue
  12. else:
  13. product = ratings.iloc[user_id - 1, indices[i]] *(similarities[i])
  14. wtd_sum = wtd_sum + product
  15. prediction = round(wtd_sum / sum_wt)
  16. # if prediction < 0:
  17. # prediction = 1
  18. # elif prediction > 10:
  19. # prediction = 10
  20. print('\nPredicted rating for user {0} -> item {1}: {2}'.format(user_id, item_id, prediction))

预测指定用户和商品的评分,并建议商品是否可以推荐给用户,如果该商品尚未被用户评分,并且预测评分排名靠前且分数大于1,则推荐给用户。

深度学习推荐模型(推荐算法和宽广神经网络模型结合)

模型

在这里插入图片描述

wide模型

wide模型就是一个形如

img

的线性模型:

img


由于使用的是乘积的形式,只有所有项都为真,最终的结果才是1,否则是0。比如"AND(gender=female,language=en)"这就是一个交叉特征,只有当用户的性别为女,并且使用的语言为英文同时成立,这个特征的结果才会是1。通过这种方式我们可以捕捉到特征之间的交互,以及为线性模型加入非线性的特征。

deep模型

deep模型就是一个前馈神经网络:输入是一个sparse的feature,可以简单理解成multihot的数组。这个输入会在神经网络的第一层转化成一个低维度的embedding,然后神经网络训练的是这个embedding。这个模块主要是被设计用来处理一些类别特征,比如说item的类目,用户的性别等等。

和传统意义上的one-hot方法相比,embedding的方式用一个向量来表示一个离散型的变量,它的表达能力更强,并且这个向量的值是让模型自己学习的,因此泛化能力也大大提升。这也是深度神经网络当中常见的做法。

Wide部分和Deep部分通过加权的方式合并在一起。

最上层输出之前是一个sigmoid层或者是一个linear层,就是一个简单的线性累加。英文叫做joint,原paper当中还列举了joint和ensemble的区别,对于ensemble模型来说,它的每一个部分是独立训练的。而joint模型当中的不同部分是联合训练的。ensemble模型当中的每一个部分的参数是互不影响的,但是对于joint模型而言,它当中的参数是同时训练的。

这样带来的结果是,由于训练对于每个部分是分开的,所以每一个子模型的参数空间都很大,这样才能获得比较好的效果。而joint训练的方式则没有这个问题,把线性部分和深度学习的部分分开,可以互补它们之间的缺陷,从而达到更好的效果,并且也不用人为地扩大训练参数的数量。

  1. '''
  2. WideDeep模型:
  3. 主要包括Wide部分和Deep部分
  4. '''
  5. class WideDeep(nn.Module):
  6. def __init__(self, feature_info, hidden_units, embed_dim=8):
  7. """
  8. DeepCrossing:
  9. feature_info: 特征信息(数值特征, 类别特征, 类别特征embedding映射)
  10. hidden_units: 列表, 隐藏单元
  11. dropout: Dropout层的失活比例
  12. embed_dim: embedding维度
  13. """
  14. super(WideDeep, self).__init__()
  15. self.dense_features, self.sparse_features, self.sparse_features_map = feature_info
  16. # embedding层, 这里需要一个列表的形式, 因为每个类别特征都需要embedding
  17. self.embed_layers = nn.ModuleDict(
  18. {
  19. 'embed_' + str(key): nn.Embedding(num_embeddings=(val), embedding_dim=embed_dim)
  20. for key, val in self.sparse_features_map.items()
  21. }
  22. )
  23. # 统计embedding_dim的总维度
  24. # 一个离散型(类别型)变量 通过embedding层变为8
  25. embed_dim_sum = sum([embed_dim] * len(self.sparse_features))
  26. # 总维度 = 数值型特征的纬度 + 离散型变量经过embedding后的纬度
  27. dim_sum = len(self.dense_features) + embed_dim_sum
  28. hidden_units.insert(0, dim_sum)
  29. # dnn网络
  30. self.dnn_network = Dnn(hidden_units)
  31. # 线性层
  32. self.linear = Linear(input_dim=len(self.dense_features))
  33. # 最终的线性层
  34. self.final_linear = nn.Linear(hidden_units[-1], 1)
  35. def forward(self, x):
  36. # print(x.shape)
  37. # 1、先把输入向量x分成两部分处理、因为数值型和类别型的处理方式不一样
  38. dense_input, sparse_inputs = x[:, :len(self.dense_features)], x[:, len(self.dense_features):]
  39. # 2、转换为long形
  40. sparse_inputs = sparse_inputs.long()
  41. # 2、不同的类别特征分别embedding
  42. sparse_embeds = []
  43. for key, i in zip(self.sparse_features_map.keys(), range(sparse_inputs.shape[1])):
  44. # print(key)
  45. # print(sparse_inputs[:, i].shape,sparse_inputs[:, i].max())
  46. # print(self.embed_layers['embed_' + key].num_embeddings)
  47. sparse_embeds.append(self.embed_layers['embed_' + key](sparse_inputs[:, i]) )
  48. # 3、把类别型特征进行拼接,即emdedding后,由3行转换为1
  49. sparse_embeds = torch.cat(sparse_embeds, axis=-1)
  50. # sparse_embeds = torch.tensor(sparse_embeds)
  51. # 4、数值型和类别型特征进行拼接
  52. dnn_input = torch.cat([sparse_embeds, dense_input], axis=1)
  53. # Wide部分,使用的特征为数值型类型
  54. wide_out = self.linear(dense_input)
  55. # Deep部分,使用全部特征
  56. deep_out = self.dnn_network(dnn_input)
  57. deep_out = self.final_linear(deep_out)
  58. # out 将Wide部分的输出和Deep部分的输出进行合并
  59. outputs = F.sigmoid(0.5 * (wide_out + deep_out))
  60. return outputs

数据预处理

  1. def prepared_data(file_path):
  2. # 读入训练集,验证集和测试集
  3. # train_set = pd.read_csv(file_path + 'train_set.csv')
  4. # val_set = pd.read_csv(file_path + 'val_set.csv')
  5. # test_set = pd.read_csv(file_path + 'test.csv')
  6. # 数值型特征直接放入stacking层
  7. dense_features = ['I' + str(i) for i in range(1, 14)]
  8. # 离散型特征需要需要进行embedding处理
  9. sparse_features = ['C' + str(i) for i in range(1, 27)]
  10. col_names_train = ['Label'] + dense_features + sparse_features
  11. data = pd.read_csv(
  12. file_path +'/train.txt',
  13. sep='\t',
  14. nrows=1000,
  15. names=col_names_train
  16. )
  17. train_set = data[:700]
  18. val_set = data[701:900]
  19. test_set = data[900:1000]
  20. # 这里需要把特征分成数值型和离散型
  21. # 因为后面的模型里面离散型的特征需要embedding, 而数值型的特征直接进入了stacking层, 处理方式会不一样
  22. data_df = pd.concat((train_set, val_set, test_set))
  23. #==================================================
  24. # 数据预处理
  25. # 2.对分类特征进行独热编码
  26. for f in sparse_features:
  27. le = LabelEncoder()
  28. data_df[f] = le.fit_transform(data_df[f])
  29. # 1、填充缺失值
  30. # 类别特征填充为-1
  31. data_df[dense_features] = data_df[dense_features].fillna('-1')
  32. # 连续特征填充为0
  33. data_df[sparse_features] = data_df[sparse_features].fillna(0)
  34. # 3、对于连续性变量进行归一化
  35. mms = MinMaxScaler()
  36. data_df[dense_features] = mms.fit_transform(data_df[dense_features])
  37. #==============================
  38. train = data_df[:700]
  39. val = data_df[701:900]
  40. test = data_df[900:1000]
  41. # 定义一个稀疏特征的embedding映射, 字典{key: value},
  42. # key表示每个稀疏特征, value表示数据集data_df对应列的不同取值个数, 作为embedding输入维度
  43. sparse_feas_map = {}
  44. for key in sparse_features:
  45. sparse_feas_map[key] = 1000000
  46. # sparse_feas_map[key] = int(data_df[key].max()) + 1
  47. # sparse_feas_map[key] = data_df[key].nunique()
  48. feature_info = [dense_features, sparse_features, sparse_feas_map] # 这里把特征信息进行封装, 建立模型的时候作为参数传入
  49. # 把数据构建成数据管道
  50. dl_train_dataset = TensorDataset(
  51. # 特征信息
  52. torch.tensor(train.drop(columns='Label').values).float(),
  53. # 标签信息
  54. torch.tensor(train['Label'].values).float()
  55. )
  56. dl_val_dataset = TensorDataset(
  57. # 特征信息
  58. torch.tensor(val.drop(columns='Label').values).float(),
  59. # 标签信息
  60. torch.tensor(val['Label'].values).float()
  61. )
  62. dl_train = DataLoader(dl_train_dataset, shuffle=True, batch_size=16)
  63. dl_vaild = DataLoader(dl_val_dataset, shuffle=True, batch_size=16)
  64. return feature_info,dl_train,dl_vaild,test

训练

  1. def train_ch(net, dl_train, dl_vaild, num_epochs, lr, device):
  2. """⽤GPU训练模型"""
  3. print('training on', device)
  4. net.to(device)
  5. # 二值交叉熵损失
  6. loss_func = nn.BCELoss()
  7. # 注意:这里没有使用原理提到的优化器
  8. optimizer = torch.optim.Adam(params=net.parameters(), lr=lr)
  9. # animator = Animator(xlabel='epoch', xlim=[1, num_epochs],legend=['train loss', 'train auc', 'val loss', 'val auc']
  10. # ,figsize=(8.0, 6.0))
  11. # timer, num_batches = Timer(), len(dl_train)
  12. log_step_freq = 10
  13. for epoch in range(1, num_epochs + 1):
  14. # 训练阶段
  15. net.train()
  16. loss_sum = 0.0
  17. metric_sum = 0.0
  18. for step, (features, labels) in enumerate(dl_train, 1):
  19. # timer.start()
  20. # 梯度清零
  21. optimizer.zero_grad()
  22. # 正向传播
  23. predictions = net(features)
  24. loss = loss_func(predictions, labels.unsqueeze(1) )
  25. try: # 这里就是如果当前批次里面的y只有一个类别, 跳过去
  26. metric = metric_func(predictions, labels)
  27. except ValueError:
  28. pass
  29. # 反向传播求梯度
  30. loss.backward()
  31. optimizer.step()
  32. # timer.stop()
  33. # 打印batch级别日志
  34. loss_sum += loss.item()
  35. metric_sum += metric.item()
  36. # if step % log_step_freq == 0:
  37. # animator.add(epoch + step / num_batches,(loss_sum/step, metric_sum/step, None, None))
  38. # 验证阶段
  39. net.eval()
  40. val_loss_sum = 0.0
  41. val_metric_sum = 0.0
  42. for val_step, (features, labels) in enumerate(dl_vaild, 1):
  43. with torch.no_grad():
  44. predictions = net(features)
  45. val_loss = loss_func(predictions, labels.unsqueeze(1))
  46. try:
  47. val_metric = metric_func(predictions, labels)
  48. except ValueError:
  49. pass
  50. val_loss_sum += val_loss.item()
  51. val_metric_sum += val_metric.item()
  52. # if val_step % log_step_freq == 0:
  53. # animator.add(epoch + val_step / num_batches, (None,None,val_loss_sum / val_step , val_metric_sum / val_step))
  54. print(f'final: loss {loss_sum/len(dl_train):.3f}, auc {metric_sum/len(dl_train):.3f},'
  55. f' val loss {val_loss_sum/len(dl_vaild):.3f}, val auc {val_metric_sum/len(dl_vaild):.3f}')
  56. # print(f'{num_batches * num_epochs / timer.sum():.1f} examples/sec on {str(device)}')

效果

由于模型较大而数据量不够,导致过拟合问题。尽管尝试了一些方法(如L1和L2正则化,Dropout等),但效果依旧不理想,最终淘汰了这个方案。这反映了在实际应用中,模型的选择和数据量的匹配至关重要。

遇到的问题和解决方案

问题1:数据稀疏性问题

描述:在协同过滤中,用户-物品评分矩阵通常非常稀疏,导致相似度计算不准确。这种稀疏性问题会影响推荐的准确性,因为相似度计算依赖于用户或物品之间的共同评分。

解决过程

  1. KNN算法填充:我们采用了KNN(K-Nearest Neighbor)算法来填充缺失的评分。通过找到与目标用户或物品最相似的K个邻居,并使用这些邻居的评分来估计缺失的评分。

  2. 数据标准化:对用户评分进行标准化处理,减小评分之间的差异。这有助于提高相似度计算的准确性。

  3. 调整后的余弦相似度:在基于物品的协同过滤中,我们使用调整后的余弦相似度(Adjusted Cosine Similarity)来计算物品之间的相似度。这种方法通过从每个共同评分对中减去各自用户的平均评分来抵消用户评分偏差的影响。

  1. from sklearn.metrics.pairwise import cosine_similarity
  2. import numpy as np
  3. # 调整后的余弦相似度
  4. def adjusted_cosine_similarity(matrix):
  5. user_means = np.mean(matrix, axis=1, keepdims=True)
  6. adjusted_matrix = matrix - user_means
  7. return cosine_similarity(adjusted_matrix)
  8. # 计算物品相似度
  9. item_similarity = adjusted_cosine_similarity(train_data.T)

问题2:模型过拟合问题

描述:由于模型复杂度高且数据量不足,导致模型过拟合。过拟合的模型在训练数据上表现良好,但在测试数据上表现不佳,这限制了模型的泛化能力。

解决过程

  1. 正则化技术:我们尝试了L1和L2正则化技术来限制模型参数的复杂度。正则化通过在损失函数中添加惩罚项来减少模型的过拟合风险。

  2. Dropout技术:在训练过程中使用Dropout技术随机丢弃一些神经元,防止网络对训练数据中的特定样本过度敏感。

  3. 早停法(Early Stopping):在训练过程中监控验证集的性能,当验证集的性能不再提升时停止训练,避免过拟合。

  1. from keras.models import Sequential
  2. from keras.layers import Dense, Dropout
  3. from keras.callbacks import EarlyStopping
  4. # 构建模型
  5. model = Sequential()
  6. model.add(Dense(64, activation='relu', input_dim=20))
  7. model.add(Dropout(0.5))
  8. model.add(Dense(1, activation='sigmoid'))
  9. # 编译模型
  10. model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
  11. # 早停法
  12. early_stopping = EarlyStopping(monitor='val_loss', patience=5)
  13. # 训练模型
  14. model.fit(train_data, train_labels, epochs=100, validation_split=0.2, callbacks=[early_stopping])

问题3:系统性能优化

描述:在处理大规模数据集时,系统的响应速度和处理能力成为瓶颈。数据库操作频繁,导致系统性能下降。

解决过程

  1. 数据库连接池:使用连接池来避免频繁地打开和关闭数据库连接,通过重用现有的数据库连接来提高效率。

  2. 缓存机制:通过使用缓存保存用户的相关记录,便于下次快速使用,这不仅提高了系统的响应速度,也减轻了数据库的压力。

  3. 批量查询:减少数据库查询次数,通过批量查询来获取数据,优化数据获取过程。

  1. from sqlalchemy import create_engine
  2. from sqlalchemy.pool import QueuePool
  3. # 使用连接池
  4. engine = create_engine('database_url', poolclass=QueuePool, pool_size=10, max_overflow=20)
  5. # 使用缓存
  6. from cachetools import cached, TTLCache
  7. cache = TTLCache(maxsize=100, ttl=300)
  8. @cached(cache)
  9. def get_user_data(user_id):
  10. return pd.read_sql_query(f"SELECT * FROM interactions WHERE user_id={user_id}", engine)

总结

在本次技术总结中,我详细介绍了我使用的几种推荐算法的实现方式及其在实际应用中的优化策略。可以看到,尽管宽广神经网络模型在理论上具有强大的特征交互能力,但由于模型复杂度高且数据量不足,导致过拟合问题,最终未能达到预期效果。这一经历强调了模型选择与数据量匹配的重要性。此外,我还总结了以下几点:

  1. 数据处理的重要性:精确的数据处理和特征工程是构建有效推荐系统的基础。通过对用户行为的细致分析和数据的精确处理,我们能够为用户提供更加个性化和准确的推荐。

  2. 模型优化的必要性:在模型训练过程中,优化数据库操作、引入缓存机制、使用连接池等措施显著提升了系统的响应速度和处理能力。

  3. 算法多样性的价值:不同的推荐算法适用于不同的场景和需求。通过结合协同过滤、基于内容的推荐、混合推荐系统和深度学习模型,我们可以更全面地满足用户的个性化需求。

  4. 持续学习和实验的重要性:在推荐系统的研究和实践中,持续的优化和实验是必不可少的。通过不断尝试和调整,可以找到最适合当前问题的模型结构和参数。

    参考文献

    传统推荐系统算法(一):协同过滤(Collaborative Filtering,CF)-CSDN博客

    推荐系统经典模型 Wide & Deep 详解 (全网之最)_wide&deep-CSDN博客

    Wide & Deep Learning for Recomender Systems

...全文
给本帖投票
122 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

109

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 防震水泥
加入社区
社区公告
暂无公告

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部