PyTorch深度神经网络及训练入门

目录

  • 图片数据预处理
    • torchvision中datasets的数据
    • 文件夹中的数据
  • 神经网络一般步骤
    • 数据准备
    • 网络的定义
    • 权重初始化
    • 损失函数和反向传播
    • 优化器
    • 总结

图片数据预处理

torchvision中datasets的数据

import torch
import torch.utils.data as Data
from torchvision.datasets import FashionMNIST
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
## 使用FashionMNIST数据,准备训练数据集
train_data  = FashionMNIST(
    root = "./data/FashionMNIST", # 数据的路径
    train = True, # 只使用训练数据集
    transform  = transforms.ToTensor(),
    download= False  #因为数据已经下载过,所以这里不再下载
)
## 定义一个数据加载器
train_loader = Data.DataLoader(
    dataset = train_data, ## 使用的数据集
    batch_size=64, # 批处理样本大小
    shuffle = True, # 每次迭代前打乱数据
    num_workers = 2, # 使用两个进程 
)
## 计算train_loader有多少个batch
print("train_loader的batch数量为:",len(train_loader))

transforms.ToTensor() 将图片(H,W,C)转换成形状为(C,H,W)的Tensor格式,且像素/255归一化到[0,1]之间。(通道为1的图片,每个像素点是一个[0,255]的数据进行表示)
n:样本数量
c:图像通道数,灰度为1,RGB为3,通道为3的图片,由3个[0,255]的数据进行混合
w:图像宽度
h:图像高度

## 对测试集进行处理
test_data  = FashionMNIST(
    root = "./data/FashionMNIST", # 数据的路径
    train = False, # 不使用训练数据集
    download= False # 因为数据已经下载过,所以这里不再下载
)
## 为数据添加一个通道纬度,并且取值范围缩放到0~1之间
test_data_x = test_data.data.type(torch.FloatTensor) / 255.0
test_data_x = torch.unsqueeze(test_data_x,dim = 1)
test_data_y = test_data.targets  ## 测试集的标签
print("test_data_x.shape:",test_data_x.shape)
print("test_data_y.shape:",test_data_y.shape)

输出结果:
test_data_x.shape: torch.Size([10000, 1, 28, 28])
test_data_y.shape: torch.Size([10000])

每张图片都是28*28的矩阵组成。

test_data_x.data[0]可得到第一张图片的28*28的矩阵。

test_data_x = torch.unsqueeze(test_data_x,dim = 1)表示在第二维增加一个1,使[10000, 28, 28]变为[10000, 1, 28, 28],表示通道数为1.

文件夹中的数据

## 对训练集的预处理
train_data_transforms = transforms.Compose([
    transforms.RandomResizedCrop(224),# 随机长宽比裁剪为224*224
    transforms.RandomHorizontalFlip(),# 依概率p=0.5水平翻转
    transforms.ToTensor(), # 转化为张量并归一化至[0-1]
    ## 图像标准化处理
    transforms.Normalize([0.485, 0.456, 0.406], 
                         [0.229, 0.224, 0.225])
])
## 读取图像
train_data_dir = "D:\BaiduNetdiskDownload\深度学习\深度学习\程序\programs.7z\programs\data\chap2\imagedata"
train_data = ImageFolder(
    train_data_dir, 
    transform=train_data_transforms
)
train_data_loader = Data.DataLoader(
    dataset = train_data,
    batch_size=4,
    shuffle=True,
    num_workers=1
)

print("数据集的label:",train_data.targets)

##  获得一个batch的数据
for step, (b_x, b_y) in enumerate(train_data_loader):  
    if step > 0:
        break
## 输出训练图像的尺寸和标签的尺寸
print(b_x.shape)
print(b_y.shape)
print("图像的取值范围为:",b_x.min(),"~",b_x.max())

输出结果:
数据集的label: [0, 0, 1, 2]
torch.Size([4, 3, 224, 224])
torch.Size([4])
图像的取值范围为: tensor(-2.1179) ~ tensor(2.6400)

有3个文件夹,第一个两张图片,第二个一张图片,第三个一张图片。

transforms.Normalize使用如下公式进行归一化:
channel=(channel-mean)/std
也就是说 ( (0,1) - 0.485 ) / 0.229 = (-2.11,2.24)
( (0,1) - 0.456 ) / 0.224 = (~ ,~)
( (0,1) - 0.406 ) / 0.225 = (~ ,2.64)

神经网络一般步骤

数据准备

import torch
import torch.nn as nn
from torch.optim import SGD
import torch.utils.data as Data
from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

boston_X,boston_y = load_boston(return_X_y=True)
print("boston_X.shape:",boston_X.shape)           #输出:boston_X.shape: (506, 13)

## 数据标准化处理
ss = StandardScaler(with_mean=True,with_std=True)
boston_Xs = ss.fit_transform(boston_X)
# boston_ys = ss.fit_transform(boston_y)
np.mean(boston_Xs,axis=0)
np.std(boston_Xs,axis=0)

## 将数据预处理为可以使用pytorch进行批量训练的形式
## 训练集X转化为张量
train_xt = torch.from_numpy(boston_Xs.astype(np.float32))
## 训练集y转化为张量
train_yt = torch.from_numpy(boston_y.astype(np.float32))
## 将训练集转化为张量后,使用TensorDataset将X和Y整理到一起
train_data = Data.TensorDataset(train_xt,train_yt)
## 定义一个数据加载器,将训练数据集进行批量处理
train_loader = Data.DataLoader(
    dataset = train_data, ## 使用的数据集
    batch_size=128, # 批处理样本大小
    shuffle = True, # 每次迭代前打乱数据
    num_workers = 2, # 使用两个进程 
)

##  检查训练数据集的一个batch的样本的维度是否正确
for step, (b_x, b_y) in enumerate(train_loader):  
    if step > 0:
        break
## 输出训练图像的尺寸和标签的尺寸,都是torch格式的数据
print(b_x.shape)
print(b_y.shape)
print(len(train_loader))

# 输出结果:
torch.Size([128, 13])            #一个batch有128组数据,每组数据13个特征值。
torch.Size([128])          #一个batch有128组标签。
4

网络的定义

## 使用继承Module的形式定义全连接神经网络
class MLPmodel(nn.Module):
    def __init__(self):
        super(MLPmodel,self).__init__()
        ## 定义第一个隐藏层
        self.hidden1 = nn.Linear(
            in_features = 13, ## 第一个隐藏层的输入,数据的特征数,上方数据特征数为13
            out_features = 10,## 第一个隐藏层的输出,神经元的数量
            bias=True, ## 默认会有偏置
        )
        self.active1 = nn.ReLU()
        ## 定义第二个隐藏层
        self.hidden2 = nn.Linear(10,10)
        self.active2 = nn.ReLU()
        ## 定义预测回归层
        self.regression = nn.Linear(10,1)

    ## 定义网络的向前传播路径   
    def forward(self, x):
        x = self.hidden1(x)
        x = self.active1(x)
        x = self.hidden2(x)
        x = self.active2(x)
        output = self.regression(x)
        ## 输出为output
        return output

mlp1 = MLPmodel()
print(mlp1)

#输出5个层:
MLPmodel(
  (hidden1): Linear(in_features=13, out_features=10, bias=True)
  (active1): ReLU()
  (hidden2): Linear(in_features=10, out_features=10, bias=True)
  (active2): ReLU()
  (regression): Linear(in_features=10, out_features=1, bias=True)
)

权重初始化

一层的初始化:

import torch
import torch.nn as nn

## 针对一个卷积层的权重初始化方法
conv1 = torch.nn.Conv2d(4,16,3)
## 使用标准正态分布分布初始化权重
torch.manual_seed(12)  ## 随机数初始化种子
torch.nn.init.normal(conv1.weight,mean=0,std=1)

conv1.weight.shape          #输出torch.Size([16, 4, 3, 3])

上方能够初始化16*4=64个卷积核。

多层的初始化:

## 定义为网络中的没个层进行权重初始化的函数
def init_weights(m):
    ## 如果是卷积层
    if type(m) == nn.Conv2d:
        torch.nn.init.normal(m.weight,mean=0,std=0.5)
    ## 如果是全连接层
    if type(m) == nn.Linear:
        torch.nn.init.uniform(m.weight,a=-0.1,b=0.1)
        m.bias.data.fill_(0.01)
        

## 使用网络的apply方法进行权重初始化
torch.manual_seed(13)  ## 随机数初始化种子
testnet.apply(init_weights)

损失函数和反向传播

通过调用forward函数,向前传播,计算输出的值和实际值之间的差距,即损失函数。

output = mlp1(b_x).flatten()      # MLP在训练batch上的输出

loss_func = nn.MSELoss()  # 最小平方根误差
train_loss = loss_func(output,b_y) # 平方根误差

反向传播:

optimizer.zero_grad()           # 每个迭代步的梯度初始化为0,即手动将梯度清零
train_loss.backward()           # 损失的后向传播,计算梯度

参考文章:
如何直观地解释 backpropagation 算法.
PyTorch中在反向传播前为什么要手动将梯度清零.

优化器

optimizer = SGD(mlp1.parameters(),lr=0.001)     #随机梯度

optimizer.step()                # 使用梯度进行优化

参考文章:
梯度下降法是如何运用到神经网络中的.

## 使用方式1
optimizer = Adam(testnet.parameters(),lr=0.001)  


## 使用方式2:为不同的层定义不同的学习率
optimizer = Adam(
    [{"params":testnet.hidden.parameters(),"lr":0.0001},
    {"params":testnet.regression.parameters(),"lr": 0.01}],
    lr=1e-2)

## 这意味着testnet.hidden的参数将会使用0.0001的学习率,
## testnet.regression的参数将会使用0.01的学习率,
## 而且lr=1e-2将作用于其它没有特殊指定的所有参数。

优化器函数中的参数就是输入的权重和偏移量。

总结

## 对回归模型mlp1进行训练并输出损失函数的变化情况
# 定义优化器和损失函数
optimizer = SGD(mlp1.parameters(),lr=0.001)  
loss_func = nn.MSELoss()  # 最小平方根误差
train_loss_all = [] ## 输出每个批次训练的损失函数
## 进行训练,并输出每次迭代的损失函数
for epoch in range(30):
    ## 对训练数据的迭代器进行迭代计算
    for step, (b_x, b_y) in enumerate(train_loader):  
        output = mlp1(b_x).flatten()      # MLP在训练batch上的输出
        train_loss = loss_func(output,b_y) # 平方根误差
        optimizer.zero_grad()           # 每个迭代步的梯度初始化为0
        train_loss.backward()           # 损失的后向传播,计算梯度
        optimizer.step()                # 使用梯度进行优化
        train_loss_all.append(train_loss.item())
  • 准备数据
  • 定义网络
  • 定义优化器和损失函数
  • 进行迭代计算
  • 获得输出并计算损失函数
  • 梯度清零和向后传播计算梯度
  • 进行优化(自动调整权重和偏移量)

你可能感兴趣的:(机器学习,神经网络,人工智能,深度学习,网络)