《动手学深度学习》上的例子
手动搭建一个能学线性回归的函数(神经网络)
def data_generate():
'''产生真实数据,这里维度为2,个数1000。同时我们增加了扰动(测量误差)'''
number_inputs = 2 #dimension of input
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = nd.random.normal(scale = 1, shape=(num_examples,number_inputs))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += nd.random.normal(scale=0.01, shape=labels.shape)
def data_iter(batch_size, features, labels):
'''生成每次训练batch里的用例'''
num_examples = len(features) #get the number of lines
indices = list(range(num_examples))
#shuffle
random.shuffle(indices)
for i in range(0, num_examples, batch_size):
j = nd.array(indices[i: min(i + batch_size, num_examples)])
# take 函数根据索引返回对应元素。 yield的用法见[这里](http://www.runoob.com/w3cnote/python-yield-used-analysis.html)
yield features.take(j), labels.take(j)
def linreg(X, w, b):
'''线性计算'''
return nd.dot(X, w) + b
def squared_loss(y_hat, y):
'''平方误差'''
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
def sgd(params, lr, batch_size):
'''更新参数'''
for param in params:
#原处更新,不申请新的内存,解释见[这里](https://blog.csdn.net/Love_wanling/article/details/81130136)
param[:] = param - lr * param.grad / batch_size
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss
#initialize the model
w = nd.random.normal(scale=0.01, shape=(number_inputs, 1))
b = nd.zeros(shape=(1,))
params = [w, b]
# 训练模型⼀共需要 num_epochs 个迭代周期。
for epoch in range(1, num_epochs + 1):
# 在⼀个迭代周期中,使⽤训练数据集中所有样本⼀次(假设样本数能够被批量⼤⼩整除)。
# X 和 y 分别是⼩批量样本的特征和标签。
for X, y in data_iter(batch_size, features, labels):
with autograd.record():
# l 是有关⼩批量 X 和 y 的损失。
l = loss(net(X, w, b), y)
# ⼩批量的损失对模型参数求导。
l.backward()
# 使⽤⼩批量随机梯度下降迭代模型参数。
sgd([w, b], lr, batch_size)
print('epoch %d, loss %f'% (epoch, loss(net(features, w, b), labels).mean().asnumpy()))
print('w: %f b: %f' % (w,b))
在实验中,发现loss变成0.000050就不动了。降低学习率,同样如此。
因为我们在产生数据的时候加了扰动,所以如此。把扰动注释掉就发现 loss=0。
注:
labels += nd.random.normal(scale=0.01, shape=labels.shape)
样本的数据的标准差为 0.01 方差为0.0001 所以loss为:0.000050