%matplotlib inline
from IPython import display
from matplotlib import pyplot as plt
from mxnet import autograd, nd
import random
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = nd.random.normal(scale=1, shape=(num_examples, num_inputs))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
def use_svg_display():
# 用矢量图显示
display.set_matplotlib_formats('svg')
def set_figsize(figsize=(3.5, 2.5)):
use_svg_display()
# 设置图的尺寸
plt.rcParams['figure.figsize'] = figsize
set_figsize()
plt.scatter(features[:, 1].asnumpy(), labels.asnumpy(), 1); # 加分号只显示图
# 本函数已保存在d2lzh包中方便以后使用
def data_iter(batch_size, features, labels): #数据迭代器,用来存储遍历所有的子集样本
num_examples = len(features)
indices = list(range(num_examples))
random.shuffle(indices) # 样本的读取顺序是随机的
for i in range(0, num_examples, batch_size):
j = nd.array(indices[i: min(i + batch_size, num_examples)])
yield features.take(j), labels.take(j) # take函数根据索引返回对应元素
batch_size=10
for x,y in data_iter(batch_size,features,labels):
print(x,y)
break
w=nd.random.normal(scale=0.01,shape=(num_inputs,1)) #c初始化模型参数
b=nd.zeros(shape=(1,))
w.attach_grad()
b.attach_grad() #申请求导内存
def linreg(X,w,b): #定义模型y^
return nd.dot(X,w)+b
def squared_loss(y_hat,y): #定义损失函数的类型,此处为平方损失,把上面的y^放到这里,即
#y_hat
return (y_hat - y.reshape(y_hat.shape))**2/2
def sgd(params,lr,batch_size): #定义参数的更新方法,lr:学习率,params指参数有多个。
for param in params:
param[:]=param-lr*param.grad/batch_size
##前面定义好了所有的东西,数据读取,参数处世权值,模型,损失函数,参数更新;最后揉到一起完成训练过程。
lr=0.03
num_epochs = 3 #epoch,即训练一次,完成一次反向传播的过程。
net = linreg
loss = squared_loss
for epoch in range(num_epochs):
for X, y in data_iter(batch_size, features, labels):
with autograd.record():
l = loss(net(X, w, b), y) # l是有关小批量X和y的损失 每一个样本求一个loss,然后给参数更新一下,最终的参数是将所有的梯度加在一起了。
l.backward() # 小批量的损失对模型参数求梯度
sgd([w, b], lr, batch_size) # 使用小批量随机梯度下降迭代模型参数
train_l = loss(net(features, w, b), labels) #最后一次迭代的损失,也即一轮结束后的损失。
print('epoch %d , loss %f' % (epoch + 1, train_l.mean().asnumpy()))