🌞欢迎来到PyTorch 的世界 
🌈博客主页:卿云阁

💌欢迎关注🎉点赞👍收藏⭐️留言📝

🌟本文由卿云阁原创!

📆首发时间:🌹2024年2月14日🌹

✉️希望可以和大家一起完成进阶之路!

🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!


目录

前言   

Tensor的创建

torch.tensor()-- torch.tensor([])

torch.randn-- torch.randperm

torch.range(begin,end,step)

指定numpy

 Tensor运算

 A.add() --A.add_()

torch.stack

CUDA

自动求导

 backward求导

autograd.grad求导

求最小值

数据

Dataset and DataLoader

DataLoader的参数如下:

Pytorch工具

         Variable(变量)

Variable 计算, 梯度

神经网络工具箱torch.nn

nn.Module类

搭建简易神经网络

torch实现一个完整的神经网络

torch.autograd

自定义传播函数

torch.nn.Sequential

torch.nn.Linear

 torch.nn.ReLU

torch.nn.MSELoss

使用损失函数的神经网络

 torch.optim



 前言    

      Torch 自称为神经网络界的 Numpy, 因为他能将 torch 产生的 tensor 放在 GPU 中加速运算 (前提是你有合适的 GPU), 就像 Numpy 会把 array 放在 CPU 中加速运算. 所以神经网络的话, 当然是用 Torch 的 tensor 形式数据最好咯. 就像 Tensorflow 当中的 tensor 一样. numpy array 和 torch tensor 是可以自由地转换的。

import torch
import numpy as np

np_data = np.arange(6).reshape((2, 3))
torch_data = torch.from_numpy(np_data)
tensor2array = torch_data.numpy()
print('\nnumpy array:', np_data)
print('\ntorch tensor:', torch_data)
print('\ntensor to array:', tensor2array)


Tensor的创建

torch.tensor()-- torch.tensor([])

二者的主要区别在于创建的对象的size和value不同

x=torch.Tensor(2,3)
print("dim:",x.dim())
print("size:",x.size())
print('------------')
y=torch.Tensor([2,3])
print("dim:",y.dim())
print("size:",y.size())

torch.randn-- torch.randperm

     生成的数据类型为浮点型,与numpy.randn生成随机数的方法类似,生成的浮点数的取值满足均值为0,方差为1的正态分布。torch.randperm(n)为创建一个n个整数,随机排列的Tensor。

x = torch.randn(3,4,requires_grad=True) #requires_grad=True表示需要求导
print("x:",x)
y = torch.randperm(3) 
print('------------')
print("y:",y)

torch.range(begin,end,step)

生成一个一维的Tensor,三个参数分别的起始位置,终止位置和步长

torch.range(1,10,2)
#结果
tensor([1., 3., 5., 7., 9.])
指定numpy

很多时候我们需要创建指定的Tensor,而numpy就是一个很好的方式

torch.Tensor(np.arange(6).reshape((2, 3)))
#结果
tensor([[0., 1., 2.],
        [3., 4., 5.]])

 Tensor运算

常见的运算
函数作用
torch.abs(A)绝对值
torch.add(A,B)相加,A和B既可以是Tensor也可以是标量
torch.clamp(A,max,min)

裁剪,A中的数据若小于min或大于max,则变成min或max,

即保证范围在[min,max]

torch.div(A,B)相除,A%B,A和B既可以是Tensor也可以是标量
torch.mul(A,B)点乘,A*B,A和B既可以是Tensor也可以是标量
torch.pow(A,n)求幂,A的n次方
 torch.mm(A,B.T)矩阵叉乘,注意与torch.mul之间的区别
torch.mv(A,B)

矩阵与向量相乘,A是矩阵,B是向量,

这里的B需不需要转置都是可以的

A.item()

将Tensor转化为基本数据类型,

注意Tensor中只有一个元素的时候才可以使用,

一般用于在Tensor中取出数值

A.numpy()将Tensor转化为Numpy类型
A.size()查看尺寸
A.shape查看尺寸
A.dtype查看数据类型
A.view()重构张量尺寸,类似于Numpy中的reshape
A.transpose(0,1)行列交换
A[1:],A[-1,-1]=100切面,类似Numpy中的切面
A.zero_()归零化
torch.stack((A,B),sim=-1)拼接,升维
torch.diag(A)取A对角线元素形成一个一维向量
torch.diag_embed(A)将一维向量放到对角线中,其余数值为0的Tensor
 A.add() --A.add_()

所有的带_符号的函数都会对原数据进行修改

import torch
a = torch.zeros(2,3)
a.add(1)
print(a)
print('------------')
a.add_(1)
print(a)

torch.stack

stack为拼接函数,函数的第一个参数为需要拼接的Tensor,第二个参数为细分到哪个维度。

A=torch.IntTensor([[1,2,3],[4,5,6]])
B=torch.IntTensor([[7,8,9],[10,11,12]])
C1=torch.stack((A,B),dim=0) # or C1=torch.stack((A,B))
C2=torch.stack((A,B),dim=1)
C3=torch.stack((A,B),dim=2)
C4=torch.stack((A,B),dim=-1)
print(C1,C2,C3,C4)

dim=0,C1 = [ A,B ]

dim=1,C2 = [ [ A[0],B[0] ] , [ A[1],B[1] ] ]

dim=2,C3 = [ [ [ A[0][0],B[0][0] ] , [ A[0][1],B[0][1] ] , [ A[0][2],B[0][2] ] ],

                        [ [ A[1][0],B[1][0] ] , [ A[1][1],B[1][1] ] , [ A[1][2],B[1][2] ] ] ]

dim=-1,C4 = C3


CUDA

CUDA是一种操作GPU的软件架构,Pytorch配合GPU环境这样模型的训练速度会非常的快。

import torch
 
# 测试GPU环境是否可使用
print(torch.__version__) # pytorch版本
print(torch.version.cuda) # cuda版本
print(torch.cuda.is_available()) # 查看cuda是否可用
 
#使用GPU or CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
# 判断某个对象是在什么环境中运行的
a.device
 
# 将对象的环境设置为device环境
A = A.to(device)
 
# 将对象环境设置为COU
A.cpu().device
 
# 若一个没有环境的对象与另外一个有环境a对象进行交流,则环境全变成环境a
a+b.to(device)
 
# cuda环境下tensor不能直接转化为numpy类型,必须要先转化到cpu环境中
a.cpu().numpy()
 
# 创建CUDA型的tensor
torch.tensor([1,2],device)

自动求导

     我们为什么要用到这些框架鸭,直接用python写代码不香嘛?难度最大的地方就是反向传播了,反向传播中需要逐层求导(w),并且这个w是一个矩阵。框架比较好的就是自动计算反向传播的求导操作。

     神经网络依赖反向传播求梯度来更新网络的参数,求梯度是个非常复杂的过程,在Pytorch中,提供了两种求梯度的方式,一个是backward,将求得的结果保存在自变量的grad属性中,另外一种方式是torch.autograd.grad。

 backward求导

   使用backward进行求导。这里主要介绍了求导的两种对象,标量Tensor和非标量Tensor的求导。两者的主要区别是非标量Tensor求导的主要区别是加了一个gradient的Tensor,其尺寸与自变量X的尺寸一致。在求完导后,需要与gradient进行点积,所以只是一般的求导的话,设置的参数全部为1。

import numpy as np
import torch
# 标量Tensor求导
# 求 f(x) = a*x**2 + b*x + c 的导数
x = torch.tensor(-2.0, requires_grad=True)
a = torch.tensor(1.0)
b = torch.tensor(2.0)
c = torch.tensor(3.0)
y = a*torch.pow(x,2)+b*x+c
y.backward() # backward求得的梯度会存储在自变量x的grad属性中
dy_dx =x.grad
dy_dx

# 非标量Tensor求导
# 求 f(x) = a*x**2 + b*x + c 的导数
x = torch.tensor([[-2.0,-1.0],[0.0,1.0]], requires_grad=True)
a = torch.tensor(1.0)
b = torch.tensor(2.0)
c = torch.tensor(3.0)
gradient=torch.tensor([[1.0,1.0],[1.0,1.0]])
y = a*torch.pow(x,2)+b*x+c
y.backward(gradient=gradient) 
dy_dx =x.grad
dy_dx

autograd.grad求导
import torch
 
#单个自变量求导
# 求 f(x) = a*x**4 + b*x + c 的导数
x = torch.tensor(1.0, requires_grad=True)
a = torch.tensor(1.0)
b = torch.tensor(2.0)
c = torch.tensor(3.0)
y = a * torch.pow(x, 4) + b * x + c
#create_graph设置为True,允许创建更高阶级的导数
#求一阶导
dy_dx = torch.autograd.grad(y, x, create_graph=True)[0]
#求二阶导
dy2_dx2 = torch.autograd.grad(dy_dx, x, create_graph=True)[0]
#求三阶导
dy3_dx3 = torch.autograd.grad(dy2_dx2, x)[0]
print(dy_dx.data, dy2_dx2.data, dy3_dx3)

# 多个自变量求偏导
x1 = torch.tensor(1.0, requires_grad=True)
x2 = torch.tensor(2.0, requires_grad=True)
y1 = x1 * x2
y2 = x1 + x2
#只有一个因变量,正常求偏导
dy1_dx1, dy1_dx2 = torch.autograd.grad(outputs=y1, inputs=[x1, x2], retain_graph=True)
print(dy1_dx1, dy1_dx2)
# 若有多个因变量,则对于每个因变量,会将求偏导的结果加起来
dy1_dx, dy2_dx = torch.autograd.grad(outputs=[y1, y2], inputs=[x1, x2])
dy1_dx, dy2_dx
print(dy1_dx, dy2_dx)

求最小值

使用自动微分机制配套使用SGD随机梯度下降来求最小值

#例2-1-3 利用自动微分和优化器求最小值
import numpy as np
import torch
 
# f(x) = a*x**2 + b*x + c的最小值
x = torch.tensor(0.0, requires_grad=True)  # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
optimizer = torch.optim.SGD(params=[x], lr=0.01)  #SGD为随机梯度下降
print(optimizer)
 
def f(x):
    result = a * torch.pow(x, 2) + b * x + c
    return (result)
 
for i in range(500):
    optimizer.zero_grad()  #将模型的参数初始化为0
    y = f(x)
    y.backward()  #反向传播计算梯度
    optimizer.step()  #更新所有的参数
print("y=", y.data, ";", "x=", x.data)


数据

Pytorch主要通过Dataset和DataLoader进行构建数据管道。

Dataset and DataLoader
Dataset一个数据集抽象类,所有自定义的Dataset都需要继承它,并且重写__getitem__()或__get_sample__()这个类方法
DataLoader一个可迭代的数据装载器。在训练的时候,每一个for循环迭代,就从DataLoader中获取一个batch_sieze大小的数据。

手动实现简单的Dataset and DataLoader

AI训练时的需求

  1. 有一个数据集文件夹,里面有100w的样本和标签
  2. 训练时,通常希望,一次在100w里随机抓取batch个样本,拿去训练
  3. 如果抓取完毕,则希望重新打乱后,再来一次

dataset,数据集

作用:存储数据集的信息  self.xxx

           获取数据集的长度    _ _len_ _

           获取数据集某特定条目的内容   _ _getitem_ _

​
class ImageDataset:
    def __init__(self,raw_data)
        self.raw_data = raw_data    
    def __len__(self)
       return len( self.raw_data) 
    def __getitem__(self,index)
        image,lable = self.raw_data[index]
        return image,lable

​
image = [[f"image{i}",i] for i in range(100)]
print(image)

dataloader,数据加载器

作用:从数据集随机加载数据,并拼接成一个batch

           实现迭代器,可以让使用时,迭代获取数据内容

class DataLoader:
    def __init__(self, dataset, batch_size):
        self.dataset = dataset
        self.batch_size = batch_size

    def __iter__(self):
        self.indexs = np.arange(len(self.dataset))
        self.cursor = 0
        np.random.shuffle(self.indexs)
        return self

    def __next__(self):
        begin = self.cursor
        end = self.cursor + self.batch_size
        if end > len(self.dataset):
            raise StopIteration()
        self.cursor = end
        batched_data = []
        for index in self.indexs[begin:end]:
            item = self.dataset[index]
            batched_data.append(item)
        return batched_data

完整代码:

import numpy as np

class ImageDataset:
    def __init__(self, raw_data):
        self.raw_data = raw_data

    def __len__(self):
        return len(self.raw_data)

    def __getitem__(self, index):
        image, label = self.raw_data[index]
        return image, label

class DataLoader:
    def __init__(self, dataset, batch_size):
        self.dataset = dataset
        self.batch_size = batch_size

    def __iter__(self):
        self.indexs = np.arange(len(self.dataset))
        self.cursor = 0
        np.random.shuffle(self.indexs)
        return self

    def __next__(self):
        begin = self.cursor
        end = self.cursor + self.batch_size
        if end > len(self.dataset):
            raise StopIteration()
        self.cursor = end
        batched_data = []
        for index in self.indexs[begin:end]:
            item = self.dataset[index]
            batched_data.append(item)
        return batched_data

# Example usage
images = [(f"image{i}", i) for i in range(100)]
dataset = ImageDataset(images)
loader = DataLoader(dataset, 5)

for index, batched_data in enumerate(loader):
    print(f"Batch {index + 1}:", batched_data)

一图胜千言:

DataLoader的参数如下:
DataLoader(
 dataset,
 batch_size=1,
 shuffle=False,
 sampler=None,
 batch_sampler=None,
 num_workers=0,
 collate_fn=None,
 pin_memory=False,
 drop_last=False,
 timeout=0,
 worker_init_fn=None,
 multiprocessing_context=None,
)
 

dataset                    数据集,决定数据从哪里读取,以及如何读取
batch_size              批次大小,默认为1
shuffle                    每个epoch是否乱序
sampler                 样本采样函数,一般无需设置
batch_sampler       批次采样函数,一般无需设置
num_workers        使用多进程读取数据,设置的进程数
collate_fn              整理一个批次数据的函数

Epoch所有的样本数据都输入到模型中,称为一个epoch
Iteration一个Batch的样本输入到模型中,称为一个Iteration
Batchsize一个批次的大小,一个Epoch=Batchsize*Iteration
 
Pytorch工具
torchvision图像视频处理
torchaudio音频处理
torchtext自然语言处理
Variable(变量)

      在 Torch 中的 Variable 就是一个存放会变化的值的地理位置. 里面的值会不停的变化. 就像一个装鸡蛋的篮子, 鸡蛋数会不停变动. 那谁是里面的鸡蛋呢, 自然就是 Torch 的 Tensor 咯. 如果用一个 Variable 进行计算, 那返回的也是一个同类型的 Variable。

import torch
from torch.autograd import Variable # torch 中 Variable 模块
# 先生鸡蛋
tensor = torch.FloatTensor([[1,2],[3,4]])
# 把鸡蛋放到篮子里, requires_grad是参不参与误差反向传播, 要不要计算梯度
variable = Variable(tensor, requires_grad=True)
print(tensor)
print("----------------------------------")
print(variable)

Variable 计算, 梯度

我们再对比一下 tensor 的计算和 variable 的计算.

t_out = torch.mean(tensor*tensor)       # x^2
v_out = torch.mean(variable*variable)   # x^2
print(t_out)
print(v_out)    # 7.5
v_out.backward()    # 模拟 v_out 的误差反向传递

# 下面两步看不懂没关系, 只要知道 Variable 是计算图的一部分, 可以用来传递误差就好.
# v_out = 1/4 * sum(variable*variable) 这是计算图中的 v_out 计算步骤
# 针对于 v_out 的梯度就是, d(v_out)/d(variable) = 1/4*2*variable = variable/2

print(variable.grad)    # 初始 Variable 的梯度
'''
 0.5000  1.0000
 1.5000  2.0000
'''

   直接print(variable)只会输出 Variable 形式的数据, 在很多时候是用不了的(比如想要用 plt 画图), 所以我们要转换一下, 将它变成 tensor 形式。

print(variable)     #  Variable 形式
"""
Variable containing:
 1  2
 3  4
[torch.FloatTensor of size 2x2]
"""

print(variable.data)    # tensor 形式
"""
 1  2
 3  4
[torch.FloatTensor of size 2x2]
"""

print(variable.data.numpy())    # numpy 形式
"""
[[ 1.  2.]
 [ 3.  4.]]
"""

神经网络工具箱torch.nn

    torch.autograd库虽然实现了自动求导与梯度反向传播,但如果我们要完成一个模型的训练,仍需要手写参数的自动更新、训练过程的控制等,还是不够便利。为此,PyTorch进一步提供了集成度更高的模块化接口torch.nn,该接口构建于Autograd之上,提供了网络模组、优化器和初始化策略等一系列功能。

nn.Module类

    nn.Module是PyTorch提供的神经网络类,并在类中实现了网络各层的定义及前向计算与反向传播机制。在实际使用时,如果想要实现某个神经网络,只需继承nn.Module,在初始化中定义模型结构与参数,在函数forward()中编写网络前向过程即可。

#这里用torch.nn实现一个MLP
from torch import nn

class MLP(nn.Module):
    def __init__(self, in_dim, hid_dim1, hid_dim2, out_dim):
        super(MLP, self).__init__()
        self.layer = nn.Sequential(
          nn.Linear(in_dim, hid_dim1),
          nn.ReLU(),
          nn.Linear(hid_dim1, hid_dim2),
          nn.ReLU(),
          nn.Linear(hid_dim2, out_dim),
          nn.ReLU()
       )
    def forward(self, x):
        x = self.layer(x)
        return x
搭建简易神经网络

下面我们用torch搭一个简易神经网络:
1、我们设置输入节点为1000,隐藏层的节点为100,输出层的节点为10。
2、输入100个具有1000个特征的数据,经过隐藏层后变成100个具有10个分类结果的特征,然后将得到的结果后向传播。

import torch

batch_n = 100  # 一个批次输入数据的数量
hidden_layer = 100
input_data = 1000  # 每个数据的特征为1000
output_data = 10

# 生成输入数据 x 和标签数据 y
x = torch.randn(batch_n, input_data)  # 生成随机输入数据,形状为 (batch_n, input_data)
y = torch.randn(batch_n, output_data)  # 生成随机标签数据,形状为 (batch_n, output_data)

# 初始化权重参数 w1 和 w2
w1 = torch.randn(input_data, hidden_layer)  # 输入层到隐藏层的权重,形状为 (input_data, hidden_layer)
w2 = torch.randn(hidden_layer, output_data)  # 隐藏层到输出层的权重,形状为 (hidden_layer, output_data)

epoch_n = 20  # 训练的总轮次
lr = 1e-6  # 学习率

# 训练过程
for epoch in range(epoch_n):
    # 前向传播
    h1 = x.mm(w1)  # 矩阵乘法,得到隐藏层的输出,形状为 (batch_n, hidden_layer)
    h1 = h1.clamp(min=0)  # 非线性激活函数,ReLU
    y_pred = h1.mm(w2)  # 矩阵乘法,得到网络的输出,形状为 (batch_n, output_data)
    
    # 计算损失
    loss = (y_pred - y).pow(2).sum()  # 平方损失,即预测值与实际值之间的差异的平方和
    print("epoch: {}, loss: {:.4f}".format(epoch, loss.item()))  # 打印当前轮次和损失
    
    # 反向传播
    grad_y_pred = 2 * (y_pred - y)  # 损失关于预测值的梯度
    grad_w2 = h1.t().mm(grad_y_pred)  # 隐藏层到输出层权重的梯度
    
    grad_h = grad_y_pred.clone()
    grad_h = grad_h.mm(w2.t())  # 输出层到隐藏层的梯度
    grad_h.clamp_(min=0)  # 非线性激活函数的梯度,ReLU
    
    grad_w1 = x.t().mm(grad_h)  # 输入层到隐藏层权重的梯度
    
    # 更新权重
    w1 = w1 - lr * grad_w1  # 使用梯度下降更新输入层到隐藏层权重
    w2 = w2 - lr * grad_w2  # 使用梯度下降更新隐藏层到输出层权重

torch实现一个完整的神经网络

torch.autograd
import torch
from torch.autograd import Variable
batch_n = 100#一个批次输入数据的数量
hidden_layer = 100
input_data = 1000#每个数据的特征为1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
#用Variable对Tensor数据类型变量进行封装的操作。requires_grad如果是False,表示该变量在进行自动梯度计算的过程中不会保留梯度值。
w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)

#学习率和迭代次数
epoch_n=50
lr=1e-6

for epoch in range(epoch_n):
    h1=x.mm(w1)#(100,1000)*(1000,100)-->100*100
    print(h1.shape)
    h1=h1.clamp(min=0)
    y_pred = h1.mm(w2)
    loss = (y_pred-y).pow(2).sum()
    print("epoch:{},loss:{:.4f}".format(epoch,loss.data))
    loss.backward()#后向传播
    w1.data -= lr*w1.grad.data
    w2.data -= lr*w2.grad.data
    w1.grad.data.zero_()
    w2.grad.data.zero_()

自定义传播函数

      其实除了可以采用自动梯度方法,我们还可以通过构建一个继承了torch.nn.Module的新类,来完成对前向传播函数和后向传播函数的重写。在这个新类中,我们使用forward作为前向传播函数的关键字,使用backward作为后向传播函数的关键字。下面我们进行自定义传播函数:

import torch
from torch.autograd import Variable
batch_n = 64#一个批次输入数据的数量
hidden_layer = 100
input_data = 1000#每个数据的特征为1000
output_data = 10
class Model(torch.nn.Module):#完成类继承的操作
    def __init__(self):
        super(Model,self).__init__()#类的初始化
        
    def forward(self,input,w1,w2):
        x = torch.mm(input,w1)
        x = torch.clamp(x,min = 0)
        x = torch.mm(x,w2)
        return x
    
    def backward(self):
        pass
model = Model()
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
#用Variable对Tensor数据类型变量进行封装的操作。requires_grad如果是F,表示该变量在进行自动梯度计算的过程中不会保留梯度值。
w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)

epoch_n=30

for epoch in range(epoch_n):
    y_pred = model(x,w1,w2)
    
    loss = (y_pred-y).pow(2).sum()
    print("epoch:{},loss:{:.4f}".format(epoch,loss.data))
    loss.backward()
    w1.data -= lr*w1.grad.data
    w2.data -= lr*w2.grad.data

    w1.grad.data.zero_()
    w2.grad.data.zero_()
torch.nn.Sequential

       torch.nn.Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络模型的搭建,最主要的是,参数会按照我们定义好的序列自动传递下去。

import torch
from torch.autograd import Variable
batch_n = 100#一个批次输入数据的数量
hidden_layer = 100
input_data = 1000#每个数据的特征为1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
#用Variable对Tensor数据类型变量进行封装的操作。requires_grad如果是F,表示该变量在进行自动梯度计算的过程中不会保留梯度值。

models = torch.nn.Sequential(
    torch.nn.Linear(input_data,hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer,output_data)
)
#torch.nn.Sequential括号内就是我们搭建的神经网络模型的具体结构,Linear完成从隐藏层到输出层的线性变换,再用ReLU激活函数激活
#torch.nn.Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络模型的搭建,
#最主要的是,参数会按照我们定义好的序列自动传递下去。
torch.nn.Linear

    torch.nn.Linear类用于定义模型的线性层,即完成前面提到的不同的层之间的线性变换。 线性层接受的参数有3个:分别是输入特征数、输出特征数、是否使用偏置,默认为True,使用torch.nn.Linear类,会自动生成对应维度的权重参数和偏置,对于生成的权重参数和偏置,我们的模型默认使用一种比之前的简单随机方式更好的参数初始化方式。

 torch.nn.ReLU

     torch.nn.ReLU属于非线性激活分类,在定义时默认不需要传入参数。当然,在torch.nn包中还有许多非线性激活函数类可供选择,比如PReLU、LeaKyReLU、Tanh、Sigmoid、Softmax等。

torch.nn.MSELoss

   torch.nn.MSELoss类使用均方误差函数对损失值进行计算,定义类的对象时不用传入任何参数,但在使用实例时需要输入两个维度一样的参数方可进行计算。

使用损失函数的神经网络
import torch
from torch.autograd import Variable
import torch
from torch.autograd import Variable
loss_fn = torch.nn.MSELoss()
x = Variable(torch.randn(100,100))
y = Variable(torch.randn(100,100))
loss = loss_fn(x,y)


batch_n = 100#一个批次输入数据的数量
hidden_layer = 100
input_data = 1000#每个数据的特征为1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
#用Variable对Tensor数据类型变量进行封装的操作。requires_grad如果是F,表示该变量在进行自动梯度计算的过程中不会保留梯度值。

models = torch.nn.Sequential(
    torch.nn.Linear(input_data,hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer,output_data)
)
#torch.nn.Sequential括号内就是我们搭建的神经网络模型的具体结构,Linear完成从隐藏层到输出层的线性变换,再用ReLU激活函数激活
#torch.nn.Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络模型的搭建,
#最主要的是,参数会按照我们定义好的序列自动传递下去。


for epoch in range(epoch_n):
    y_pred = models(x)
    
    loss = loss_fn(y_pred,y)
    if epoch%1000 == 0:
        print("epoch:{},loss:{:.4f}".format(epoch,loss.data))
    models.zero_grad()
    
    loss.backward()
    
    for param in models.parameters():
        param.data -= param.grad.data*lr
 torch.optim

torch.optim包提供非常多的可实现参数自动优化的类,如SGD、AdaGrad、RMSProp、Adam等使用自动优化的类实现神经网络:

import torch
from torch.autograd import Variable

batch_n = 100#一个批次输入数据的数量
hidden_layer = 100
input_data = 1000#每个数据的特征为1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
#用Variable对Tensor数据类型变量进行封装的操作。requires_grad如果是F,表示该变量在进行自动梯度计算的过程中不会保留梯度值。

models = torch.nn.Sequential(
    torch.nn.Linear(input_data,hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer,output_data)
)
#torch.nn.Sequential括号内就是我们搭建的神经网络模型的具体结构,Linear完成从隐藏层到输出层的线性变换,再用ReLU激活函数激活
#torch.nn.Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络模型的搭建,
#最主要的是,参数会按照我们定义好的序列自动传递下去。

# loss_fn = torch.nn.MSELoss()
# x = Variable(torch.randn(100,100))
# y = Variable(torch.randn(100,100))
# loss = loss_fn(x,y)

epoch_n=10000
lr=1e-4
loss_fn = torch.nn.MSELoss()

optimzer = torch.optim.Adam(models.parameters(),lr=lr)
#使用torch.optim.Adam类作为我们模型参数的优化函数,这里输入的是:被优化的参数和学习率的初始值。
#因为我们需要优化的是模型中的全部参数,所以传递的参数是models.parameters()

#进行,模型训练的代码如下:
for epoch in range(epoch_n):
    y_pred = models(x)
    loss = loss_fn(y_pred,y)
    print("Epoch:{},Loss:{:.4f}".format(epoch,loss.data))
    optimzer.zero_grad()#将模型参数的梯度归0
    
    loss.backward()
    optimzer.step()#使用计算得到的梯度值对各个节点的参数进行梯度更新。

其它操作参考:API

参考文献:

【1】【Pytorch】2024 Pytorch基础入门教程(完整详细版)_pytorch教程-CSDN博客

【2】带你用pytorch搞深度学习!!!_狂干两万字带你用pytorch搞深度学习-CSDN

【3】变量 (Variable) | 莫烦Python (mofanpy.com)

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐