从最简单的线性回归开始。
线性回归求参数w和b,有直接快速的最小二乘法,但是这里用到的是梯度下降法。
设损失函数为平方损失函数,即所有预测y值与训练真实y值之差的平方之和。
那么即可根据梯度下降公式a = a - η*(∂L/∂a) 来更新参数。
注意,学习速率η过大会导致震荡而不收敛;过小则会导致收敛过慢。
代码如下。
import numpy as np
class Linear_Regression(object):
def __init__(self, learning_rate=0.001, max_iter=1000, init_w=0.0, init_b=0.0):
self.learning_rate = learning_rate
self.max_iter = max_iter
self.w = init_w
self.b = init_b
def fit(self, train_X, train_Y):
for i in range(self.max_iter):
predict_Y = self.w * train_X + self.b
loss_a = np.sum(np.square(train_Y - predict_Y)) #更新参数前的损失
dldw = np.sum((train_Y - predict_Y) * (-1) * train_X) #损失函数对参数w求导
dldb = np.sum((train_Y - predict_Y) * (-1)) #损失函数对参数b求导
temp_w = self.w - self.learning_rate * dldw #梯度下降更新参数w
temp_b = self.b - self.learning_rate * dldb #梯度下降更新参数b
predict_Y = temp_w * train_X + temp_b
loss_b = np.sum(np.square(train_Y - predict_Y)) #更新参数后的损失
if loss_b - loss_a > 0:
break #如果更新参数后损失变大了, 说明要么已经收敛, 要么学习速率过大出现震荡
else:
self.w = temp_w #否则, 确认本次参数更新
self.b = temp_b
def get_parameters(self):
print("w = %.3f, b = %.3f"%(self.w, self.b))
return self.w, self.b
def predict(self, test_X):
predict_Y = self.w * test_X + self.b
print(predict_Y)
return predict_Y