首页人工智能Pytorch10.感知机实例、链式法则...

10.感知机实例、链式法则、2D函数优化实例

1.单输出的单层感知机实例:

import torch
from torch.nn import functional as F

# 输入有10个特征
x = torch.rand(1,10)
w = torch.rand(1,10,requires_grad=True)
# 对输出用sigmoid函数激活处理
o = torch.sigmoid(x @ w.t())
print('输出值o为:',o)
print('输出值o的shape为:',o.shape)
# 计算损失mse
loss = F.mse_loss(torch.ones(1,1),o)
print('损失值为:',loss)
print('损失值的shape为:',loss.shape)
# 计算梯度,得到loss对w的导数
loss.backward()
print('loss对w的导数为:',w.grad)

结果:

输出值o为: tensor([[0.9597]], grad_fn=<SigmoidBackward>)
输出值o的shape为: torch.Size([1, 1])
损失值为: tensor(0.0016, grad_fn=<MeanBackward1>)
损失值的shape为: torch.Size([])
loss对w的导数为: tensor([[-0.0024, -0.0008, -0.0013, -0.0026, -0.0027, -0.0004, -0.0030, -0.0014,-0.0021, -0.0017]])

2.多输出的单层感知机实例:

import torch
from torch.nn import functional as F

# 输入有10个特征
x = torch.rand(1,10)
# 因为要实现多输出,因此w的维度不再是1,本次为2个输出
w = torch.rand(2,10,requires_grad=True)
# 对输出用sigmoid函数激活处理
o = torch.sigmoid(x @ w.t())
print('输出值o为:',o)
print('输出值o的shape为:',o.shape)
# 计算损失mse
loss = F.mse_loss(torch.ones(1,2),o)
print('损失值为:',loss)
print('损失值的shape为:',loss.shape)
# 计算梯度,得到loss对w的导数
loss.backward()
print('loss对w的导数为:',w.grad)

结果:

输出值o为: tensor([[0.9151, 0.8192]], grad_fn=<SigmoidBackward>)
输出值o的shape为: torch.Size([1, 2])
损失值为: tensor(0.0200, grad_fn=<MeanBackward1>)
损失值的shape为: torch.Size([])
loss对w的导数为: tensor([[-0.0054, -0.0041, -0.0005, -0.0012, -0.0039, -0.0020, -0.0027, -0.0003,
         -0.0019, -0.0019],
        [-0.0219, -0.0167, -0.0019, -0.0049, -0.0159, -0.0079, -0.0109, -0.0012,
         -0.0077, -0.0076]])

3.链式法则实例:

链式法则是求复合函数的导数(偏导数)的法则,可以表示为如下式子:

其中的x相当于输入,y相当于输出,u相当于神经网络中的hidden layer

使用链式法则会让神经网络的求解变得非常简洁和清晰。

import torch

x = torch.tensor(1.1)

w1 = torch.tensor(2.2,requires_grad=True)
b1 = torch.tensor(1.1)

w2 = torch.tensor(2.2,requires_grad=True)
b2 = torch.tensor(1.1)

y1 = x*w1 + b1
y2 = y1*w2 + b2

# 使用链式法则求解
dy2_dw1 = torch.autograd.grad(y2,[w1],retain_graph=True)[0]
print(dy2_dw1)

# 使用逐步求解
dy2_dy1 = torch.autograd.grad(y2,[y1],retain_graph=True)[0]
dy1_dw1 = torch.autograd.grad(y1,[w1],retain_graph=True)[0]
print(dy2_dy1*dy1_dw1)

结果:

tensor(2.4200)
tensor(2.4200)

4.2D函数(Himmelblau函数)优化实例:

Himmelblau函数表达式如下所示:

该函数有四处极值点,为:

Himmelblau函数用于检测优化器效果。

  • 首先将函数可视化出来。
import numpy as np
from matplotlib import pyplot as plt
# matplotlib版本在1.0.x以上时需导入下面工具,否则会报错ValueError: Unknown projection '3d'
from mpl_toolkits.mplot3d import Axes3D

def Himmelblau(x):
	return (x[0]**2 + x[1] - 11)**2 + (x[0] + x[1]**2 -7)**2

x = np.arange(-6,6,0.1)
y = np.arange(-6,6,0.1)
print(x.shape,y.shape)

# meshgrid()方法从一个坐标向量中返回一个坐标矩阵
X,Y = np.meshgrid(x,y)
print(X.shape,Y.shape)

Z = Himmelblau([X,Y])

fig = plt.figure('Himmelblau')
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z)
ax.view_init(60,-30)
ax.set_xlabel('X')
ax.set_ylabel('Y')
plt.show()

得到如下图形:

  • 使用随机梯度下降优化
import torch

def himmelblau(x):
	return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 - 7) ** 2

# 初始化
x = torch.tensor([0., 0.], requires_grad=True)
# 优化目标是找到使himmelblau函数值最小的坐标x[0],x[1]
# 这里使用Adam优化器,优化目标为x,学习率为1e-3
optimizer = torch.optim.Adam([x], lr=1e-3)

for i in range(20000):
	# 每次计算出当前的函数值
	pred = himmelblau(x)
	# 因为梯度是被积累的而不是被替换掉,每次需将梯度设置为0
	optimizer.zero_grad()
	# 求得梯度信息
	pred.backward()
	# 使用上一步得到的梯度更新参数
	optimizer.step()
	# 每2000次输出下
	if i % 2000 == 0:
		print("step={},x={},f(x)={}".format(i, x.tolist(), pred.item()))

结果如下:

step=0,x=[0.0009999999310821295, 0.0009999999310821295],f(x)=170.0
step=2000,x=[2.3331806659698486, 1.9540692567825317],f(x)=13.730920791625977
step=4000,x=[2.9820079803466797, 2.0270984172821045],f(x)=0.014858869835734367
step=6000,x=[2.999983549118042, 2.0000221729278564],f(x)=1.1074007488787174e-08
step=8000,x=[2.9999938011169434, 2.0000083446502686],f(x)=1.5572823031106964e-09
step=10000,x=[2.999997854232788, 2.000002861022949],f(x)=1.8189894035458565e-10
step=12000,x=[2.9999992847442627, 2.0000009536743164],f(x)=1.6370904631912708e-11
step=14000,x=[2.999999761581421, 2.000000238418579],f(x)=1.8189894035458565e-12
step=16000,x=[3.0, 2.0],f(x)=0.0
step=18000,x=[3.0, 2.0],f(x)=0.0

可以看出很容易找到局部最小值,改变初始化状态将会得到不同的结果。
说明初始化状态对机器学习其实是很重要的。

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments