以房屋价格为例:x1:面积(输入),x2:房龄(输入),b偏移量,y房屋价格(输出)
(1)生成数据集:
y=w1X+w2X2+b+c(噪声)
%matplotlib inline
from IPython import display
from matplotlib import pyplot as plt
from mxnet import autograd,nd
import random
num_input=2
num_example=1000 #生成1000个数据
true_w=[2,-3.4] #w1 w2
true_b=4.2 #b
c=nd.random.normal(scale=0.01, shape=labels.shape) #c服从均值0,方差0.01正态分布
features=nd.random.normal(scale=1,shape=(num_example,num_input))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += c #labels=w1X+w2X2+b+c
(2)随机取样
要想使得预测值与真实值接近,定义损失函数:
损失函数值最小的时候w1,w2,b为解
求解过程一般使用 小批量随机梯度下降:我们先选取⼀组模型参数的初始值,例如随机选取;接
下来对参数进⾏多次迭代,使得每次迭代都可能降低损失函数的值。在每次迭代中,我们先随机
均匀采样⼀个由固定数⽬训练数据样本所组成的小批量(mini-batch)B;然后求小批量中数据
样本的平均损失有关模型参数的导数(梯度);最后⽤此结果与预先设定的⼀个正数的乘积作为
模型参数在本次迭代的减小量。
|B| 代表每个小批量中的样本个数(批量⼤小,batch size),η 称作学习率(learning
rate)并取正数
随机取样
def data_iter(batch_size,feature,labels):
num_example=len(feature)
indices=list(range(num_example))
random.shuffle(indices)
for i in range(0,num_example,batch_size):
j=nd.array(indices[i,min(i+bitch_size,num_example)])
yield frature.take(j),labels.take(j)
batch_size=10
for x,y in data_iter(batch_size,features,labels):
print(x,y)
break
[[ 0.5524477 0.48631126]
[-0.8952654 0.10170649]
[ 1.1726456 -0.3430832 ]
[ 0.5406341 1.0568132 ]
[-0.5444709 0.0167956 ]
[ 2.3545127 2.7097657 ]
[-0.8027809 -1.1629785 ]
[-2.1919975 -1.2398797 ]
[-0.10655522 0.6688192 ]
[-0.6416009 0.47119406]]
<NDArray 10x2 @cpu(0)>
[ 3.648315 2.062205 7.705526 1.7100557 3.0541918 -0.2880056
6.5460396 4.0411267 1.7185655 1.3050058]
<NDArray 10 @cpu(0)>
(3)初始化模型参数
对需要最后的求解w,b 我们需先将其初始化
w=nd.random.normal(scale=0.01, shape=(num_input,1))
b=nd.zeros(shape=(1,))
w.attach_grad() #创建梯度
b.attach_grad()
(4)定义模型
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:
param[:] = param - lr * param.grad / batch_size
(5)线性回归
lr=0.03 #学习率:取正数,超参数非训练得出
num_epochs=3 #迭代次数
for epoch in range(num_epochs):
for X,y in data_iter(batch_size,feature,labels):
with autograde.record():
l=loss(linreg(X,w,b),y)
l.wockback()
sgd([w,b],lr,batch_size)
print(true_b,b)
print(true_w,w)
最后比较训练结果和生成数据的真实值的,非常相似
4.2
[4.199993]
<NDArray 1 @cpu(0)>
[2, -3.4]
[[ 1.9996347]
[-3.3999841]]
<NDArray 2x1 @cpu(0)>
最后,附上全部程序,在jupyter全部运行通过
%matplotlib inline
from IPython import display
from matplotlib import pyplot as plt
from mxnet import autograd,nd
import random
num_input=2
num_example=1000
true_w=[2,-3.4]
true_b=4.2
batch_size=10
features=nd.random.normal(scale=1,shape=(num_example,num_input))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
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()
#plt.scatter(features[:, 1].asnumpy(), labels.asnumpy(), 1);
def data_iter(batch_size,feature,labels):
num_example=len(feature)
indices=list(range(num_example))
random.shuffle(indices)
for i in range(0,num_example,batch_size):
j=nd.array(indices[i:min(i+batch_size,num_example)])
yield feature.take(j),labels.take(j)
#for x,y in data_iter(batch_size,features,labels):
# print(x,y)
#break
w = nd.random.normal(scale=0.01, shape=(num_input, 1))
b = nd.zeros(shape=(1,))
w.attach_grad()
b.attach_grad()
#print(w,b)
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:
param[:] = param - lr * param.grad / batch_size
lr = 0.03
num_epochs = 3
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 的损失。
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()))
print(true_b,b)
print(true_w,w)