赞
踩
先导入包
- %matplotlib inline
- from IPython import display
- from matplotlib import pyplot as plt
- from mxnet import autograd, nd
- import random
features为随机生成服从(0,1)正态分布的数据2000个,形状为1000*2,labels就是目标变量,这里已经设定好权重w1,w2分别为2,-3.4,还有b为4.2,最后一行是给目标变量加上噪声,这样跟真实数据更为接近。
- 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)) #1000*2
- labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b #1000*1
- labels += nd.random.normal(scale=0.01, shape=labels.shape) #加上噪声
-
- 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(figsize=(5,5))
- plt.scatter(features[:, 1].asnumpy(), labels.asnumpy(),10); # 加分号只显示图
- plt.scatter(features[:, 0].asnumpy(), labels.asnumpy(),10);
画了个图,看看x1和x2与labels的关系:
可以看到x1与labels大体成正相关,x2与labels大体成负相关
- # 该函数作用是从样本中随机提取大小为batch_size的数据
- def data_iter(batch_size, features, labels):
- num_examples = len(features)
- indices = list(range(num_examples))
- random.shuffle(indices) # 样本的读取顺序是随机的 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函数根据索引返回对应元素 最后结果为生成器
接着设定函数data_iter为后面小批量随机梯度下降算法做准备,该函数的作用是从features样本中随机提取若干个数据,例如batch_size 为10时,随机的将这1000条数据(每条数据有两个值)分成100份,生成一个生成器,生成器可以当成列表,能用for循环依次提取。
正式开始:
- w = nd.random.normal(scale=0.01, shape=(num_inputs, 1))
- b = nd.zeros(shape=(1,))
-
- w.attach_grad()#申请相应内存来存x的导数。
- b.attach_grad()
-
- def linreg(X, w, b): # 本函数已保存在d2lzh包中方便以后使用
- return nd.dot(X, w) + b
- def squared_loss(y_hat, y): # 本函数已保存在d2lzh包中方便以后使用
- return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
- def sgd(params, lr, batch_size): # 本函数已保存在d2lzh包中方便以后使用
- for param in params:
- param[:] = param - lr * param.grad / batch_size
根据(0,0.01)正态分布随机生成w,b直接设置为0,attach_grad申请内存,linreg函数根据w,b,x的值来计算估计的y,squared_loss函数计算预测y值与真实y值的差的平方除以2,sgd函数对w1,w2,b值进行更新,注意sgd函数这里的for循环,里面更新params参数的方式,其中param的地址是和params一样的,所以改变param里面的值的同时params的值也会发生改变,并且直接在param上进行修改,不会新开辟内存,是目前最优的方式。
- lr = 0.03
- num_epochs = 3
- net = linreg
- loss = squared_loss
- for epoch in range(num_epochs): # 训练模型一共需要num_epochs个迭代周期
- # 在每一个迭代周期中,会使用训练数据集中所有样本一次(假设样本数能够被批量大小整除)。X
- # 和y分别是小批量样本的特征和标签
- for X, y in data_iter(batch_size, features, labels):
- with autograd.record(): #记录方便后面backward
- l = loss(net(X, w, b), y) # l是有关小批量X和y的损失
- 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()))
这里设置学习速度为0.03,迭代次数为3,注意这里l.backward后,就可以用w.grad和b.grad 的方式得出l分别对w,b求导后所得值,然后根据这些值,用sgd函数进一步进行计算就可以得到更新后的w,b值,for循环data_iter得到的生成器,就是随机小批量的优化算法,大大提升了算法的速度
-
- print(true_w, w)
-
- print(true_b, b)
-
- 结果:
- [2, -3.4]
- [[ 1.9999498]
- [-3.3991547]]
- <NDArray 2x1 @cpu(0)>
- 4.2
- [4.1989775]
- <NDArray 1 @cpu(0)>
有任何问题,欢迎留言讨论
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。