通过梯度下降优化cost实现回归模型
问题描述
你将使用住房价格预测的例子。训练数据集包含三个例子,有四个特征(尺寸、卧室、楼层和,年龄),如下表所示。
建立一个线性回归模型,这样你就可以预测其他房子的价格。
导入相关库
import copy,math
import numpy as np
np.set_printoptions(precision=2)
创建数据集
x_train = np.array([[2104, 5, 1, 45], [1416, 3, 2, 40], [852, 2, 1, 35]])
y_train = np.array([460, 232, 178])
设置最优初始值w,b
b_init = 785.1811367994083
w_init = np.array([ 0.39133535, 18.75376741, -53.36032453, -26.42131618])
损失函数设定
有多个变量的损失函数J(w,b)的方程式是:
其中:
def compute_cost(x,y,w,b):
m = x.shape[0]
cost = 0.0
for i in range(m):
f_wb_i = np.dot(x[i],w)+b
# 预测值-真实值
cost = cost+(f_wb_i-y[i])**2 # 标量
cost = cost/(2*m) # 标量
return cost
计算多变量的梯度
参数Wj,b,同时更新,其中:
def compute_gradient(x,y,w,b):
m,n = x.shape # (m:样本数 n:特征数)
# 设置为更新之前的w,b的初始值
dj_dw = np.zeros((n,))
dj_db = 0. # 表示0是一个浮点数值
# 计算当前样本的预测值与真实值之间的误差
for i in range(m):
err = (np.dot(x[i],w)+b) - y[i]
# 前面的循环在每个样本上都计算了误差值err,下一个循环
# 将误差err乘以该样本上的第j个特征上的取值x[i,j],得到
# 该特征对特度的贡献
for j in range(n):
# 更新该样本(j)的dj_dw,即特征值
dj_dw[j] = dj_dw[j]+err*x[i,j]
# 在线性回归中,模型参数的更新是基于每个样本的误差。
# 对于截距项 b,它的梯度是每个样本误差的累加总和。
# 所以,我们需要在每个样本上更新截距项的梯度,然后在循环结束时求
# 得总体的截距项梯度。
dj_db = dj_db + err
dj_dw = dj_dw / m
dj_db = dj_db / m
return dj_db,dj_dw
多变量梯度下降
# 执行批量梯度下降以学习theta。通过采取学习率为α的num_iters梯度步骤来更新θ。
def gradient_descent(X,y,w_in,b_in,cost_function,gradient_function,alpha,num_iters):
# 创建一个数组,用于存储每次迭代的成本J和W,主要用于以后的绘图
J_history = []
w = copy.deepcopy(w_in)
b = b_in
for i in range(num_iters):
# 计算梯度更新参数
dj_db,dj_dw = gradient_function(X,y,w,b)
# 计算w,b,alpha和梯度更新参数
w = w - alpha * dj_dw
b = b - alpha * dj_db
# 在每次迭代中保存成本J
if i < 100000:
J_history.append(cost_function(X,y,w,b))
# 每隔十次就打印一次成本,如果<10,则打印相同次数的迭代
# 将总的迭代次数划分为10个不同的部分
if i%math.ceil(num_iters / 10) == 0:
print(f"Iteration {i:4d}: Cost {J_history[-1]:8.2f} ")
return w,b,J_history
初始化参数
# 初始化参数
initial_w = np.zeros_like(w_init)
initial_b = 0.
# 一些梯度下降的设置
iterations = 1000
alpha = 5.0e-7
# 运行梯度下降算法
w_final, b_final, J_hist = gradient_descent(x_train, y_train, initial_w, initial_b,
compute_cost,compute_gradient,
alpha, iterations)
print(f"b,w found by gradient descent: {b_final:0.2f},{w_final} ")
m,_ = x_train.shape
for i in range(m):
print(f"prediction: {np.dot(x_train[i], w_final) + b_final:0.2f}, target value: {y_train[i]}")