笔者一直在ipad上做手写笔记,最近突然想把笔记搬到博客上来,也就有了下面这些。因为本是给自己看的笔记,所以内容很简陋,只是提了一些要点。随缘更新。
y = b + w ⋅ x y = b + w·x y=b+w⋅x
y = b + ∑ w i x i y = b + \sum w_ix_i y=b+∑wixi
L ( w , b ) = ∑ i = 1 n ( y i − ( b + w i ⋅ x i ) ) 2 L(w,b)= \sum_{i=1}^{n}\left ( y_i - (b + w_i·x_i) \right )^2 L(w,b)=i=1∑n(yi−(b+wi⋅xi))2
L越小,说明模型误差越小。
w ∗ = a r g min x L ( w ) w^* = arg\ \underset{x}{\operatorname{\min}} L(w) w∗=arg xminL(w)
随机取一个点,重复 w 0 − η ∂ L ∂ w ∣ w = w 0 w_0 - \eta\frac{\partial L}{\partial w}|_{w=w_0} w0−η∂w∂L∣w=w0 → w 1 w_1 w1( η \eta η为学习率),直到找到最优点。
Δ L = [ ∂ L ∂ w ∂ L ∂ b ] \Delta L= \begin{bmatrix} \frac{\partial L}{\partial w} \\ \\ \frac{\partial L}{\partial b} \end{bmatrix} ΔL=⎣⎡∂w∂L∂b∂L⎦⎤
由于是随机取 w 0 w_0 w0,我们有可能找到的是局部最小值,而不是全局最小值。
在模型上我们可以进一步优化,选择更复杂的模型。如一元二次方程。但更复杂的方程会导致在训练集上表现良好,但是在测试集上表现很差。
L ( w , b ) = ∑ i = 0 n ( y i − ( b + w i ⋅ x i ) ) 2 + λ ∑ w i 2 L(w,b)= \sum_{i=0}^{n}\left ( y_i - (b + w_i·x_i) \right )^2+\lambda\sum w_i^2 L(w,b)=i=0∑n(yi−(b+wi⋅xi))2+λ∑wi2
假设真实的模型为 f ^ \hat f f^,通过数据我们得到的理想模型是 f ∗ f^* f∗。
E ( f ‾ ) E(\overline{f} ) E(f)与 f ^ \hat f f^的差距称为bias。
s 2 = 1 N ∑ n ( f ‾ − f ^ ) 2 s^2=\frac{1}{N} \sum_{n}(\overline{f}-\hat f)^2 s2=N1n∑(f−f^)2
代表模型与模型之间的误差
我们可以对损失函数的变化进行可视化,手动调整
举一个简单的思想:随着次数的增加,通过一些因子来减少学习率
通常刚开始,初始点会距离最低点比较远,所以使用大一点的学习率
update好几次参数之后呢,比较靠近最低点了,此时减少学习率
比如 η t = η t t + 1 \eta^t =\frac{\eta^t}{\sqrt{t+1}} ηt=t+1ηt, t t t 是次数。随着次数的增加, η t \eta^t ηt 减小
学习率不能是一个值通用所有特征,不同的参数需要不同的学习率
将每个参数的学习率都除以之前微分的方均根:
w t + 1 = w t − η t σ t g t w^{t+1} = w^t - \frac{\eta^t}{\sigma^t}g^t wt+1=wt−σtηtgt
化简:
w t + 1 = w t − η ∑ ( g i ) 2 g t w^{t+1}=w^t-\frac{\eta}{\sqrt{\sum{(g^i)^2}}}g^t wt+1=wt−∑(gi)2ηgt
梯度越大,就和最优点的距离越远这个说法在多参数的情况下未必成立,所以最好的步伐为
一 次 微 分 二 次 微 分 \frac{一次微分}{二次微分} 二次微分一次微分
∑ ( g i ) 2 \sqrt{\sum{(g^i)^2}} ∑(gi)2就是希望在不增加计算的情况下,去模拟二次微分。
损失函数不需要训练所有的数据,而是一个或部分数据,在常规算法走一步的时候,随机算法已经走了好几十步了。虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。但是相比于普通的梯度下降,这样的方法更快,更快收敛,虽然不是全局最优,但很多时候是我们可以接受的。
下图左边这种情况,不用Adagrad是很难处理的,两个方向需要不同的学习速率。但是如果是同一学习率,模型会先收敛至类似峡谷的裂缝中,然后再以极其缓慢的速度收敛至最优点,这时标准化可以将参数 w w w都处理至同一维度,例如[-1,1]之间,这样可以有效避免出现一个参数已经收敛至最优点,但是另一个参数距离最优点还很远的情况。
如何找到红圈内 L ( θ ) L(\theta) L(θ)最小?
我们来自己实现一个简单的线性回归
# 线性回归
class LinearRegression:
'''@param
learning_rate: 学习率
n_iters: 迭代次数
epsilon: 容忍度
'''
def __init__(self, learning_rate=0.01, epsilon=1e-8, n_iters=10000):
# 初始化 Linear Regression 模型
self.learning_rate = learning_rate
self.epsilon = epsilon
self.n_iters = n_iters
self.w = None # 模型参数
def fit(self, x_train, y_train):
# 定义损失函数
def cost(w, x_b, y):
try:
return np.sum((y - x_b@w) ** 2) / len(y)
except:
return float('inf')
# 对损失函数求 w和b的导
def Derivatives(w, x_b, y):
return (-2 * (y - x_b @ w).T @ x_b / len(y)).reshape(x_b.shape[1], 1)
def gradient_descent(x_b, y, w):
for i in range(self.n_iters):
gradient = Derivatives(w, x_b, y) # 计算梯度
last_theta = w
w = w - self.learning_rate * gradient
if (abs(cost(w, x_b, y) - cost(last_theta, x_b, y)) < self.epsilon):
break
return w
x_b = np.hstack([x_train, np.ones((len(x_train), 1))])
self.w = np.zeros((x_b.shape[1], 1)) # 初始化 w
self.w = gradient_descent(x_b, y_train, self.w)
def predict(self, x_predict):
# 给定待预测数据集X_predict,返回表示X_predict的结果向量
x_b = np.hstack([x_predict, np.ones((len(x_predict), 1))])
return x_b@self.w
def score(self, x_test, y_test):
# 根据测试数据集 x_test 和 y_test 确定当前模型的准确度
y_predict = self.predict(x_test)
# 计算y_test和y_predict之间的MSE
MSE = np.sum((y_test - y_predict) ** 2) / len(y_test)
# 计算y_test和y_predict之间的R Square
return 1 - MSE / np.var(y_test)
(如果觉得有用请点个赞吧)