回归的应用十分广泛,首先回顾一下回归的定义和建模步骤
定义
Regression 就是找到一个 f u n c t i o n function function ,通过输入特征 x x x,输出一个数值 S c a l a r Scalar Scalar。1
建模步骤
- 选择模型框架
- 一元线性模型
- 多元线性模型
- 一元N次也是线性模型
- 确定损失函数
- 最小平方误差
- 优化模型(后文对误差章节进一步详述)
- 梯度下降:参数更新的效率取决于当前点的求导值和步长
- ▽ L = [ ∂ L ∂ w , ∂ L ∂ b ] \bigtriangledown L =[\dfrac{\partial L}{\partial w}, \dfrac{\partial L}{\partial b}] ▽L=[∂w∂L,∂b∂L]
- 凸函数,故可以找到最优解
常见问题
Overfitting和Regularization:过拟合和正则化
误差的来源
要想使回归模型更加准确,需要减小误差,这也是我们优化模型的方向。首先需要知道模型产生的误差,来自何方,是否可以人为的减少。
- bias: 预测值相对真实值的偏差,总体的差距,可以理解成瞄准的位置,与模型选择有关。
- variance:模型预测值的方差,多次实验之间的离散程度。
根据参考文献2,模型的误差部分分解如上图所示,该图把预测值与真实值之间的差异以一种近似向量的靶子图形表示出来。因噪声影响产生的样本值
y
y
y以及预测值的期望
E
(
f
(
x
)
^
)
E(\hat{f(x)})
E(f(x)^)均为某个邻域内的值,即不是固定的某个值,而是受区域限制。可以看出,偏差的大小与模型选择关系甚密。一个合适的模型,偏差不会很大。
- 公式:
E ( ( y − f ( x ) ^ ) 2 ) = σ 2 + V a r [ f ( x ) ^ ] + ( B i a s [ f ( x ) ^ ] ) 2 E((y− \hat{f(x)})^2)=σ ^2+Var[ \hat{f(x)}]+(Bias[ \hat{f(x)}]) ^2 E((y−f(x)^)2)=σ2+Var[f(x)^]+(Bias[f(x)^])2
误差的期望值 = 噪音的方差 + 模型预测值的方差 + 预测值相对真实值的偏差的平方2
考虑不同的模型:用比较简单的模型,方差是比较小的。如果用了复杂的模型,方差就很大,散布比较开。足够多的模型,也更可能得到真正的y,即偏差会变小。
也就是说,随着模型复杂度提高,模型bias变小,variance变大。,如下图所示3。
选择模型的宗旨和方法
- 具体选择方法:交叉验证,如N折交叉验证
- 宗旨:
欠拟合:重新设计选择模型
过拟合:更多的数据或者模型简化
梯度下降
下面回顾梯度下降算法。这之前我们需要思考,为什么不直接寻找误差为0的点,而是去找梯度趋于0的点?
三个tip
- 调整学习速率
- 随机梯度下降法
- 特征缩放:参数范围一致化
PyTorch 实践
本人新手小白,在学习pytorch,很多函数也在不断探索,该样例参考网易云pytorch课程进行编写,欢迎大家指正。
#准备数据
x_data = np.random.rand(100)
noise = np.random.normal(0,0.01,x_data.shape)
y_data = x_data*0.1 + 0.2 + noise
x_data = x_data.reshape(-1,1)
'''
我们不知道x_data的shape属性是多少,
但是想让x_data变成只有一列,行数不知道
多少,通过`x_data.reshape(-1,1)`,
Numpy自动计算出有100行,新的数组shape属
性为(100, 1),与原来的(1, 100)配套。
'''
y_data = y_data.reshape(-1,1)
x_data = torch.FloatTensor(x_data)
y_data = torch.FloatTensor(y_data)
inputs = Variable(x_data)
target = Variable(y_data)
#设计模型
class LR(nn.Module):
def __init__(self):
super(LR, self).__init__() #父类初始化
self.fc = nn.Linear(1,1) #输入一个值,输出一个值
def forward(self, x): #定义网络计算
out = self.fc(x)
return out
model = LR()
mse_loss = nn.MSELoss()
#梯度下降法优化参数
optimizer = optim.SGD(model.parameters(), lr = 0.1)
#训练模型
for i in range(1001):
out = model(inputs)
#计算loss
ls = mse_loss(out, target)
#梯度清零
optimizer.zero_grad()
#反向计算梯度,计算之前需要清0
ls.backward()
optimizer.step()
if i%200 == 0:
print(i, ls.item())
LeeML-Notes回归:https://datawhalechina.github.io/leeml-notes/#/chapter3/chapter3 ↩︎
偏差(Bias)和方差(Variance)——机器学习中的模型选择.https://segmentfault.com/a/1190000016447144 ↩︎
LeeML-Notes.误差来自哪里:https://datawhalechina.github.io/leeml-notes/#/chapter3/chapter3 ↩︎