《PyTorch深度学习实践》

1.线性模型

线性模型
y ^ = x ∗ w \widehat{y}=x*w y =xw
损失函数
l o s s = ( y ^ − y ) 2 loss=(\widehat{y}-y)^2 loss=(y y)2

import numpy as np 
import matplotlib.pyplot as plt 

x_data=[1,2,3]
y_data=[2,4,6]

def y_hat(x,w):
    return x*w
def loss(x,y):
    return (y_hat(x,w)-y)**2
w_list,mse_list=[],[]
for w in np.arange(0,4,0.1):
    # print('w={}'.format(w),sep='')
    # print('w={}'.format(w))
    cur_loss=0
    for x_i,y_i in zip(x_data,y_data):
        cur_loss+=loss(x_i,y_i)
    w_list.append(w)
    mse_list.append(cur_loss/3)
    # print(cur_loss)

plt.figure(figsize=(4,2))
plt.plot(w_list,mse_list)
plt.xlabel('w')
plt.ylabel('mse')
plt.show()

在这里插入图片描述
模型
y ^ = x ∗ w + b \widehat{y}=x*w+b y =xw+b
损失函数
l o s s = ( y ^ − y ) 2 loss=(\widehat{y}-y)^2 loss=(y y)2

mse_list=[]
for w in np.arange(0,4,0.1):
    mse_cur=[]
    for b in np.arange(-2,2,0.1):
        cur_loss=0
        for x_i,y_i in zip(x_data,y_data):
            cur_loss+=loss_3d(x_i,y_i)
        mse_cur.append(cur_loss/3)
    mse_list.append(mse_cur)
w=np.arange(0,4,0.1)
b=np.arange(-2,2,0.1)

plt.contourf(w,b,mse_list)
plt.xlabel('w')
plt.ylabel('b')
plt.show()

在这里插入图片描述

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
fig = plt.figure()
ax = Axes3D(fig)
mse_list_copy=np.array(mse_list)
ww,bb=np.meshgrid(w,b)#40x40每行相同 40x40每列相同
surf=ax.plot_surface(ww,bb,mse_list_copy, rstride=1, cstride=1, cmap=cm.coolwarm,)

ax.set_zlim(0,35)
ax.set_xlabel('w')
ax.set_ylabel('b')
ax.set_zlabel('mse')
ax.set_title('figure')
fig.colorbar(surf, shrink=0.5, aspect=5)

在这里插入图片描述

2.梯度下降

梯度消失
局部最优解(深度学习算法中,并没有过多的局部最优点。)

在这里插入图片描述

x_data=[1,2,3]
y_data=[2,4,6]

w=1
alpha=0.01
def cost(xn,yn):
    cost=0
    for x,y in zip(xn,yn):
        cost+=(x*w-y)**2
    return cost/len(xn)

def gradient(xn,yn):
    grad=0
    for x,y in zip(xn,yn):#共用一个w,可以并行计算加速
        grad+=2*x*(x*w-y)
    return grad/len(xn)
pos=[]
w_list=[]
cost_list=[]
for epoch in range(20):
    w-=alpha*gradient(x_data,y_data)
    pos.append(epoch)
    w_list.append(w)
    cost_list.append(cost(x_data,y_data))
    # if epoch%100==0:
    #     print(cost(x_data,y_data))
    #     print(w)

#并行计算,计算20轮,本应60,实际时间20
import matplotlib.pyplot as plt 
plt.figure(figsize=(5,3))

plt.plot(pos, w_list, color='green', label='w_list')
plt.plot(pos, cost_list, color='red', label='cost_list')
plt.legend()

plt.show()

在这里插入图片描述

## SGD 

x_data=[1,2,3]
y_data=[2,4,6]

w=1
alpha=0.01
def cost(xn,yn):
    cost=0
    for x,y in zip(xn,yn):
        cost+=(x*w-y)**2
    return cost/len(xn)

def gradient(x,y):
    return 2*x*(x*w-y)
    
pos=[]
w_list=[]
cost_list=[]
for epoch in range(20):
    cur_pos=epoch*len(x_data)
    for x_i,y_i in zip(x_data,y_data):#w前后依赖,不能并行计算
        w-=alpha*gradient(x_i,y_i)
        pos.append(cur_pos)
        w_list.append(w)
        cost_list.append(cost(x_data,y_data))
    # if epoch%100==0:
    #     print(cost(x_data,y_data))
    #     print(w)

#不能并行计算,计算20轮,本应60,实际时间60
import matplotlib.pyplot as plt 
plt.figure(figsize=(5,3))

plt.plot(pos, w_list, color='green', label='w_list')
plt.plot(pos, cost_list, color='red', label='cost_list')
plt.legend()

plt.show()

在这里插入图片描述

随机梯度下降法和梯度下降法的主要区别在于:
1、损失函数由cost()更改为loss()。cost是计算所有训练数据的损失,loss是计算一个训练函数的损失。对应于源代码则是少了两个for循环。
2、梯度函数gradient()由计算所有训练数据的梯度更改为计算一个训练数据的梯度。
3、本算法中的随机梯度主要是指,每次拿一个训练数据来训练,然后更新梯度参数。本算法中梯度总共更新20(epoch)x3 = 60次。梯度下降法中梯度总共更新20(epoch)次。

梯度下降:整体算(mini batch=n),性能高(一轮内部有多个样本并行计算,w的更新是相互独立的),效果差。
随机梯度下降:一个一个算(mini batch=1),性能差(计算相同规模,计算时间是梯度下降n倍),效果好。
折衷:引入mini batch,批量的随机梯度下降。

3.反向传播

简单模型的损失函数更新值可以用解析式进行表示,当遇到复杂模型时,解析式复杂,难以直接表示。基于链式求导法则,引入反向传播。
在这里插入图片描述

线性模型无论叠加多少层都会化简为一层,因此引入非线性因素(激活函数),使得神经网络可以逼近任意的非线性函数。
在这里插入图片描述
在这里插入图片描述

此外,在线性模型的基础上套一个映射函数可以实现分类。(如Sigmoid是R上的x→R上的f(x)→[0,1]上的p)

import torch
x_data=[1,2,3]
y_data=[2,4,6]

w=torch.Tensor([1])
w.requires_grad=True
def forward(x):
    return x*w
def loss(x,y):
    y_pred=forward(x)
    return (y_pred-y)**2
alpha=0.01
for epoch in range(100):
    for x,y in zip(x_data,y_data):
        l=loss(x,y)#前向计算
        l.backward()#反向传播
        w.data-=alpha*w.grad.data
        w.grad.data.zero_()
    print(epoch,l.item())

1.w是Tensor(张量类型),Tensor中包含data和grad,data和grad也是Tensor。grad初始为None,调用l.backward()方法后w.grad为Tensor。
Tensor:w(带计算图) w.grad(带计算图) w.data w.grad.data
标量:xx.item()
取w.grad.data是不会构建计算图的。
2.w是Tensor, forward函数的返回值也是Tensor,loss函数的返回值也是Tensor
3.本算法中反向传播主要体现在,l.backward()。调用该方法后w.grad由None更新为Tensor类型,且w.grad.data的值用于后续w.data的更新。
4.如果w需要计算梯度,那构建的计算图中,跟w相关的tensor都默认需要计算梯度。l.backward()会把计算图中所有需要梯度(grad)的地方都会求出来,然后把梯度都存在对应的待求的参数中,最终计算图被释放。
在这里插入图片描述
在这里插入图片描述

import torch
x_data=[1,2,3]
y_data=[2,4,6]

w1,w2,b=torch.Tensor([[1],[1],[1]])
w1.requires_grad=w2.requires_grad=b.requires_grad=True
def forward(x):
    return w1*x*x+w2*x+b
def loss(x,y):
    y_pred=forward(x)
    return (y_pred-y)**2
alpha=0.01
for epoch in range(100):
    for x,y in zip(x_data,y_data):
        l=loss(x,y)
        l.backward()
        w1.data-=alpha*w1.grad.data
        w2.data-=alpha*w2.grad.data
        b.data-=alpha*b.grad.data
        w1.grad.data.zero_()
        w2.grad.data.zero_()
        b.grad.data.zero_()
    print(epoch,l.item())

4 Pytorch实现线性回归

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

%%time
import torch
x_data=torch.Tensor([[1],[2],[3]])
y_data=torch.Tensor([[2],[4],[6]])

class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel,self).__init__()
        self.linear=torch.nn.Linear(1,1)
    def forward(self,x):
        y_pred=self.linear(x)
        return y_pred
model=LinearModel()
criterion=torch.nn.MSELoss(size_average=False)
optimizer=torch.optim.SGD(model.parameters(),lr=0.01)

for epoch in range(1000):
    y_pred=model(x_data)
    loss=criterion(y_pred,y_data)
    if epoch%100 ==0:
        print(epoch,loss.item())

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

print('w=',model.linear.weight.item())
print('b=',model.linear.bias.item())
x_test=torch.Tensor([[4]])
y_test=model(x_test)
print(y_test.item())
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值