一、L1、L2正则化
正则化是机器学习中用于防止过拟合并提高模型泛化能力的技术。当模型过拟合时,它已经很好地学习了训练数据,甚至是训练数据中的噪声,所以可能无法在新的、未见过的数据上表现良好。
比如:
其中,x1和x2为特征,f为拟合模型,w1和w2为模型权重,b为模型偏执。左图拟合模型公式最高阶次为1,即一条直线,对应欠拟合;中间拟合模型公式最高阶次为2,即一条简单的曲线;右图拟合模型公式最高阶次为4甚至更高,即一条复杂的曲线,对应过拟合。
可以看出,欠拟合时模型未有效学习数据中的信息,错分样本很多;过拟合时模型学习过于充分,甚至连包裹在红色类中的两个明显的噪声都被学习了,训练样本不会被错分,但无法保证对没见过的测试样本进行有效划分。所以更希望得到中间的这种模型。
对比中图和右图,容易发现模型阶次越高,分类超平面弯曲越多,高阶项前系数越大,弯曲程度越大,所以减少过拟合其实就是要减少模型的高阶次或弱化高阶项。
1、L1正则化
也称为LASSO正则化,将模型权重系数的绝对值之和添加到损失函数中。它能够将模型中某些权重置0使对应的特征不再发挥作用以达到降低模型复杂度的作用。
假设原本模型的分类损失为标准交叉熵,则加上L1正则化项后如下:
其中,yi和pi是样本xi的真实标签和预测概率,wj为权重系数,λ用来平衡学习和正则化程度。
有了后面这一项,在优化损失时,|wj|会一定程度地减小,从而达到弱化高阶项的作用(其实低阶项也会被弱化,但分类超平面的复杂度主要受高阶项控制)。其实,L1正则化能达到使模型稀疏化的作用,即有些权重被置0。
简化上面的损失函数只有一个权重系数,写作J(w)=L(w)+λ|w|,假设L(w)在w=0时的导数如下:
于是有:
如果λ较大,会使损失函数的导数在w=0的左右两侧异号,则该点极可能是一个极小值点,在优化时,很可能将w优化至0。对于多个w的情况,与之类似,但只是一部分w取0即可达到极小值。部分w置0,则对应的特征不在发挥作用,从而使模型稀疏化。
L1正则化能够通过使模型稀疏化达到降低模型复杂度的作用。这种稀疏化特性使它能够作为一种特征选择策略,适合在高维且特征相关性不强的场景中使用。
2、L2正则化
也称为Ridge正则化,将模型系数的平方值之和添加到损失函数中。与L1正则化不同,L2正则化不会强制系数恰好为0,而是鼓励系数变小。
仍然假设原本模型的分类损失为标准交叉熵,则加上L2正则化项后如下:
同样地,简化上面的损失函数只有一个权重系数,写作J(w)=L(w)+λw²,假设L(w)在w=0时的导数如下:
有:
可见,L2正则项的加入不影响w=0处损失函数的导数,也就不容易在w=0处形成极小值。响应地,w就不容易被优化为0。对于多个w的情况,所有wj都不为0,却又希望损失J(w)小,就会将各个wj优化的很小,也就使高阶项发挥的作用变小,从而降低模型复杂度。
L2正则化能够通过将各项权重系数优化得很小以达到降低模型复杂度的目的。它能够减少单个特征在模型中的作用,避免某个特征主导整个预测方向。L2正则化项是可微的,优化计算效率更高,适合处理低维且特征间具有强相关性的场景。
二、self-attention
python
class SelfAttention(nn.Module):
def __init__(self, hidden_dim):
super(SelfAttention, self).__init__()
self.query_matrix = nn.Linear(hidden_dim, hidden_dim, bias=False)
self.key_matrix = nn.Linear(hidden_dim, hidden_dim, bias=False)
self.value_matrix = nn.Linear(hidden_dim, hidden_dim, bias=False)
self.dropout = nn.Dropout(0.1)
self.scale = torch.sqrt(torch.FloatTensor([hidden_dim])).to(device)
def forward(self, x):
batch_size, seq_len, hidden_dim = x.size()
Q = self.query_matrix(x)
K = self.key_matrix(x)
V = self.value_matrix(x)
scores = torch.matmul(Q, K.transpose(1,2))
scaled_scores = scores / self.scale
attn_weights = torch.softmax(scaled_scores, dim=-1)
attn_weights = self.dropout(attn_weights)
attn_output = torch.matmul(attn_weights, V)
return attn_output, attn_weights
三、稳定版softmax
python
import math
def softmax(x):
max_x = max(x)
exp_x = [math.exp(i - max_x) for i in x]
sum_exp_x = sum(exp_x)
return [i / sum_exp_x for i in exp_x]
四、推荐冷启动问题如何解决?
冷启动问题的核心在于推荐系统通常依赖历史数据(如协同过滤方法需要用户和物品的交互数据),而冷启动阶段数据不足,使得传统算法无法直接运作。
冷启动问题是推荐系统的常见难题,分为三种情况:
- 新用户冷启动:对新用户缺乏行为记录,无法判断其兴趣。
- 新物品冷启动:新物品没有被用户交互过,无法确定其推荐价值。
- 冷启动用户与物品同时存在:既有新用户又有新物品时,推荐更加困难。
1、缓解冷启动问题的核心思路
(1)新用户冷启动解决方法
- 通过用户的人口统计学信息或外部行为(如第三方登录数据)
- 采用冷启动推荐算法:如基于内容、基于规则或通过预训练的模型。
(2)新物品冷启动解决方法
- 借助物品的内容信息,如物品的描述、类别、图片等。
- 使用生成模型或特征嵌入学习。
(3)冷启动用户与物品同时存在
- 利用外部知识图谱或迁移学习,弥补用户-物品交互的缺失。
2、解决冷启动的技术实现
(1)基于内容的推荐
①原理
- 对用户:基于用户的属性(年龄、职业、地区等)找到相似用户并推荐其喜欢的内容。
- 对物品:利用物品的内容信息(文本描述、类别标签、图像特征等),通过相似度计算进行推荐。
②实现步骤 - 提取用户或物品的特征向量
- 计算向量相似度
- 根据相似度推荐最相关的物品
python
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
#假设物品的内容特征
item_features = np.array([
[1,0,0],
[0,1,0],
[1,1,0],
])
new_item = np.array([[0,1,1]])
similarites = cosine_similarity(new_item, item_features)
print("相似度:", similarites)
recommended_item_index = np.argmax(similarites)
print("推荐物品ID:", recommended_item_index)