Python 练习题 --- 梯度下降
- 题目要求
- 思路讲解
- 第一题
- 第二题
- 第一步
- 第二步
- 第三步
- 第四步
- 第五步
- 改进
- 题目来源:
在校课程老师布置的作业
。
题目要求
已知某系统模型可由
对该系统实际采样得到 4
个样本:(0,3.1)
、(1,4.9)
、(2,7.2)
、(3,8.9)
根据采样数据使用一维线性回归算法估计该模型:
选取损失函数:
基于 梯度下降算法 估计参数 w
和 b
。
提示:
其中:
-
n
是样本数,(,)是样本点,
问题:
- 假设初始值
w = 0
,b = 0
,学习率η= 0.01
,根据已采集的4
个样本,基于 梯度下降算法 估计w
和b
,请计算 第1次 至 第3次 迭代的结果,要求 给出计算过程 及 每次迭代后的平均误差 。
- 假设初始值
w = 0
,b = 0
,请用python
编程计算学习率为η= 0.01
和η= 0.001
时迭代100
次的结果。
思路讲解
这道题就是简单的 梯度下降 ,公式已经给出来了,我们就直接按照公式实现即可。
第一题
第一题要求手写,有了初始条件 ,很容易写出来梯度下降的过程。
我写了个程序输出,代码如下:
w = 0
b = 0
eta = 0.01
def process():
global w, b
x = x_train.reshape(1, -1)[0]
y_hat = x * w + b
y = y_train.reshape(1, -1)[0]
diff = y - y_hat
print('(' + '+'.join(map(lambda x:str(round(x, 4)), diff**2)) + f')/{2*x.shape[0]} =', round((diff**2 / (2*x.shape[0])).sum(), 4))
grad_w = -diff * x
print('(' + '+'.join(map(lambda x:f'({round(x, 4)})', grad_w)) + f')/{x.shape[0]} =', round(grad_w.sum() / x.shape[0], 4))
w -= eta * grad_w.sum() / x.shape[0]
print('w =', w)
grad_b = -diff
print('(' + '+'.join(map(lambda x:f'({round(x, 4)})', grad_b)) + f')/{x.shape[0]} =', round(grad_b.sum() / x.shape[0], 4))
b -= eta * grad_b.sum() / x.shape[0]
print('b =', b)
for i in range(1, 4):
print('Epoch', i)
process()
print()
-
Epoch 1
: -
Epoch 2
: -
Epoch 3
:
第二题
要计算 η= 0.01
和 η= 0.001
时的结果,我们可以把能复用的地方封装成函数,以简化我们的代码。
第一步
首先要 初始化数据:
w = 0
b = 0
X = [0., 1., 2., 3.]
Y = [3.1, 4.9, 7.2, 8.9]
- 学习率我们可以作为参数传递给函数
第二步
计算 。
def forward(w, X, b):
result = []
for x in X:
result.append(w*x+b)
return result
第三步
计算 损失 loss
def get_loss(X, Y, Y_PRED):
result = []
for i, y in enumerate(Y):
result.append((y - Y_PRED[i])**2)
return sum(result) / (2 * len(X))
第四步
迭代
计算损失 ,并 更新 w
和 b
,传入参数 学习率 η
。
- 将初始化数据加入函数中,这样每次更改学习率进行训练就不需要再初始化数据。
def train(eta):
global w, b
x_train = [0., 1., 2., 3.]
y_train = [3.1, 4.9, 7.2, 8.9]
for step in range(1, 101):
y_pred = forward(w, x_train, b)
loss = get_loss(x_train, y_train, y_pred)
print('Epoch {}: loss = {}'.format(step, loss))
w -= -eta * sum([x * (y - y_hat) for x, y, y_hat in zip(x_train, y_train, y_pred)]) / len(x_train)
b -= -eta * sum([y - y_hat for y, y_hat in zip(y_train, y_pred)]) / len(x_train)
第五步
传参
。调用 train
函数。
η= 0.01
train(0.01)
print('w=', w, 'b=', b)
η= 0.001
train(0.001)
print('w=', w, 'b=', b)
改进
- 使用
numpy
数组进行计算操作会更简便。 -
封装成类
会更好看。 - (当然,我的作业包括以上两点)