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())