PyTorch技术和深度学习——三、深度学习快速入门

文章目录

      • 1.线性回归
        • 1)介绍
        • 2)加载自由泳冠军数据集
        • 3)从0开始实现线性回归模型
        • 4)使用自动求导训练线性回归模型
        • 5)使用优化器训练线性回归模型
      • 2.使用torch.nn模块构建线性回归模型
        • 1)使用torch.nn.Linear训练线性回归模型
        • 2)使用torch.nn.Sequential类训练线性回归模型
        • 3)使用torch.nn.Module训练线性回归模型
      • 3.逻辑回归
        • 1)介绍
        • 2)从0开始实现逻辑回归模型
        • 3)使用Pytorch实现逻辑回归模型
      • 4.softmax回归
        • 1)介绍
        • 2)从头开始实现softmax回归
        • 3)使用Pytorch实现softmax回归
      • 5.神经网络
        • 1)神经元
        • 2)激活函数
          • 1.绘制Sigmoid激活函数
          • 2.绘制双曲正切Tanh激活函数
          • 3.绘制ReLU激活函数
          • 4.绘制LeakyReLU激活函数
          • 5.softmax函数
          • 6.选择正确的激活函数
        • 3)神经网络原理
        • 4)Pytorch实现神经网络
        • 5)神经网络应用示例一
        • 6)神经网络应用示例二
        • 7)两层神经网络解决异或问题
        • 8)Fizz Buzz神经网络实现

1.线性回归

1)介绍

模型构建步骤:

1.定义:找到目标函数,将输入属性映射为输出属性。

2.模型假设:用一条直线拟合数据

3.模型评估:采用损失函数来评价预测值和真实值的接近程度。argmin是机器学习常用的函数,用来寻找使损失函数最小时的参数取值。

4.梯度下降算法:也叫最速下降法。用来求代价函数(损失函数或者叫目标函数)的最小值。基本思想:随机选择一组参数初始值,计算损失或者代价,然后寻找能让代价下降最多的另一组参数,反复迭代直至达到一个局部最优。

2)加载自由泳冠军数据集

数据集为奥运会自由泳冠军数据,

创建文件display_olympics_freestyle100m.py
添加代码如下:

import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorx = dataset_tensor[:, :-1]y = dataset_tensor[:, -1]# 绘图plt.plot(x.numpy(), y.numpy(), 'o')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.show()if __name__ == "__main__":main()

运行结果:
在这里插入图片描述

横坐标为奥运举办年份,纵坐标为取胜时间

3)从0开始实现线性回归模型

思路:

1.建立线性回归模型;

2.损失函数及损失函数求导

3.利用损失函数求导,实现梯度函数

梯度下降的收敛可以通过设置最大迭代次数或者判断参数不再改变来确定已经收敛。更新参数使用全部样本成为批量梯度下降法(BGD);使用一个样本成为随机梯度下降法(SGD);使用部分样本叫小批量梯度下降法,兼顾前两种优缺点。

4.重复:计算预测值(前向传播),然后计算损失和梯度;更新参数;

创建文件linear_regression_from_scratch.py
实现代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现线性回归模型
"""
import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def grad_loss_fn(y_pred, y):""" 损失函数求导 """return 2 * (y_pred - y)def grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = grad_loss_fn(y_pred, y) * xgrad_b = grad_loss_fn(y_pred, y)return torch.stack([grad_w.mean(), grad_b.mean()])def model_training(x, y, n_epochs, learning_rate, params, print_params=True):""" 训练 """for epoch in range(1, n_epochs + 1):w, b = params# 前向传播y_pred = model(x, w, b)# 计算损失loss = loss_fn(y_pred, y)# 梯度grad = grad_fn(x, y, y_pred)# 更新参数params = params - learning_rate * gradif epoch == 1 or epoch % 500 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))if print_params:print(f'参数:{params.detach().numpy()}')print(f'梯度:{grad.detach().numpy()}')return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 模型参数初始化w = torch.zeros(1)b = torch.zeros(1)# 直接用未优化的模型来预测y_pred = model(x, w, b)print('未优化的模型的预测结果:', y_pred.detach().numpy())loss = loss_fn(y_pred, y)print('未优化的模型的损失:', loss.detach().numpy())params = model_training(x=x,y=y,n_epochs=50000,learning_rate=0.00017,params=torch.tensor([0.0, 0.0]))print('梯度下降找到的w和b:%f %f \n' % (params[0], params[1]))y_pred = model(x, *params)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

运行结果:

在这里插入图片描述

4)使用自动求导训练线性回归模型

pytorch提供自动求导功能,计算梯度。只要提供前向表达式,就可以计算任意节点梯度。

只需要在张量的构造中添加requires_grad=True参数即可。

detach().requires_grad_()表示将张量分离同时设置requires_grad=True。

创建文件linear_regression_autograd.py
完整实现代码如下:

# -*- coding: utf-8 -*-
"""
使用自动求导训练线性回归模型
"""import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x, y, params, n_epochs, learning_rate):""" 训练 """for epoch in range(1, n_epochs + 1):# 梯度清零if params.grad is not None:params.grad.zero_()# 前向传播y_pred = model(x, *params)# 计算损失loss = loss_fn(y_pred, y)# 反向传播loss.backward()# 更新参数params = (params - learning_rate * params.grad).detach().requires_grad_()if epoch == 1 or epoch % 500 == 0:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 初始化模型参数params = torch.tensor([0.0, 0.0], requires_grad=True)print('params.grad is None: ', params.grad is None)loss = loss_fn(model(x, *params), y)loss.backward()print(params.grad)if params.grad is not None:params.grad.zero_()params = model_training(x=x,y=y,params=torch.tensor([0.0, 0.0], requires_grad=True),n_epochs=50000,learning_rate=0.00017)print('梯度下降找到的w和b:%f %f \n' % (params[0], params[1]))y_pred = model(x, *params)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
5)使用优化器训练线性回归模型

优化器(optimizer)用来优化梯度计算。包括SGD 优化,Adam。

创建文件linear_regression_optimizers.py
完整实现代码如下:

# -*- coding: utf-8 -*-
"""
使用优化器训练线性回归模型 
"""import torch
import torch.optim as optim
import pandas as pd
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x, y, params, n_epochs, optimizer):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播p_pred = model(x, *params)# 计算损失loss = loss_fn(p_pred, y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 500 == 0:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 参数params = torch.tensor([0.0, 0.0], requires_grad=True)learning_rate = 0.00017# 使用optim模块中的现成优化器optimizer = optim.SGD([params], lr=learning_rate)# 手工做一次优化y_pred = model(x, *params)loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 优化loss.backward()optimizer.step()# 打印一次优化后的参数print('一次优化后的参数:', params)# 手工再做一次优化params = torch.tensor([0.0, 0.0], requires_grad=True)optimizer = optim.SGD([params], lr=learning_rate)y_pred = model(x, *params)loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 优化loss.backward()optimizer.step()# 打印再一次优化后的参数print('再一次优化后的参数:', params)print('\n使用SGD训练模型')params = torch.tensor([0.0, 0.0], requires_grad=True)optimizer = optim.SGD([params], lr=learning_rate)params = model_training(x=x,y=y,params=params,n_epochs=50000,optimizer=optimizer)print('SGD优化器找到的w和b:%f %f \n' % (params[0], params[1]))print('\n使用Adam再训练一次模型')# 注意学习率和训练轮次都不同于SGD,说明Adam是高级优化函数params = torch.tensor([0.0, 0.0], requires_grad=True)learning_rate = 1e-1optimizer = optim.Adam([params], lr=learning_rate)params = model_training(x=x,y=y,params=params,n_epochs=2000,optimizer=optimizer)print('Adam优化器找到的w和b:%f %f \n' % (params[0], params[1]))# 再做一次预测y_pred = model(x, *params)# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

2.使用torch.nn模块构建线性回归模型

pytorch提供nn模块,包含有Lineaar、Sequential、Model和各种损失函数。

1)使用torch.nn.Linear训练线性回归模型

步骤:

1.加载数据集,划分划分训练集验证集

2.定义线性模型

3.设置优化器

4.分别使用自定义的损失函数和nn模块使用开箱即用的损失函数

# -*- coding: utf-8 -*-
"""
使用torch.nn.Linear训练线性回归模型
"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)with torch.no_grad():y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_train = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_train]val_idx = shuffled_idx[n_train:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型linear_model = nn.Linear(1, 1)# 使用optim模块中的现成优化器learning_rate = 1e-1epochs = 3000optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用自定义的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=epochs,optimizer=optimizer,model=linear_model,loss_fn=loss_fn)print()print(linear_model.weight)print(linear_model.bias)linear_model = nn.Linear(1, 1)optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=epochs,optimizer=optimizer,model=linear_model,loss_fn=nn.MSELoss())print('优化后的模型参数')print(linear_model.weight)print(linear_model.bias)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), linear_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), linear_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
2)使用torch.nn.Sequential类训练线性回归模型

Sequential是一种容器,添加并连接模块,最终形成一个网络模型。

创建文件linear_regression_nn_sequential.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
使用torch.nn.Sequential类训练线性回归模型"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():learning_rate = 1e-1# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_trin = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_trin]val_idx = shuffled_idx[n_trin:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型# 读者可尝试使用两种模型定义中的一种,看看有什么区别# 第一种定义# seq_model = nn.Sequential(#         nn.Linear(1, 10),#         nn.LogSigmoid(),#         nn.Linear(10, 1)# )# 第二种定义from collections import OrderedDictseq_model = nn.Sequential(OrderedDict([('hidden_linear', nn.Linear(1, 10)),('hidden_activation', nn.LogSigmoid()),('output_linear', nn.Linear(10, 1))]))# 打印模型信息print(seq_model)for name, param in seq_model.named_parameters():print("{:21} {:19} {}".format(name, str(param.shape), param.numel()))optimizer = optim.Adam(seq_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=3000,optimizer=optimizer,model=seq_model,loss_fn=nn.MSELoss())print('优化后的模型参数')for name, param in seq_model.named_parameters():print(name, param)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), seq_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), seq_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
3)使用torch.nn.Module训练线性回归模型

使用nn.Module实现自定义线性模型。

创建文件linear_regression_nn_module.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
使用torch.nn.Module训练线性回归模型
"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falseclass LinearModel(nn.Module):""" 自定义模型 """def __init__(self):super().__init__()self.hidden_linear = nn.Linear(1, 10)self.activation = nn.LogSigmoid()self.output_linear = nn.Linear(10, 1)def forward(self, input):output = self.hidden_linear(input)output = self.activation(output)output = self.output_linear(output)return outputdef model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():learning_rate = 1e-1# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_trin = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_trin]val_idx = shuffled_idx[n_trin:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型linear_model = LinearModel()# 打印模型信息print(linear_model)for name, param in linear_model.named_parameters():print("{:21} {:19} {}".format(name, str(param.shape), param.numel()))optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=3000,optimizer=optimizer,model=linear_model,loss_fn=nn.MSELoss())print('优化后的模型参数')for name, param in linear_model.named_parameters():print(name, param)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), linear_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), linear_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

3.逻辑回归

线性回归解决回归问题;逻辑回归主要解决分类问题。区别在于前者目标值连续;后者是离散的。

可以将逻辑回归视为神经网络的一个神经元

1)介绍

思路:

1.假设函数:使用激活函数求输出。Sigmoid函数很好模拟了阶跃函数

2.代价函数:求代价使用负对数似然代价函数表示。

3.逻辑回归梯度下降算法

2)从0开始实现逻辑回归模型

创建文件logistic_regression_from_scratch.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现逻辑回归模型
"""import torch
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef sigmoid(z):""" S型激活函数 """g = 1 / (1 + torch.exp(-z))return gdef model(x, w, b):""" 逻辑回归模型 """return sigmoid(x.mv(w) + b)def loss_fn(y_pred, y):""" 损失函数 """loss = - y.mul(y_pred.view_as(y)) - (1 - y).mul(1 - y_pred.view_as(y))return loss.mean()def grad_loss_fn(y_pred, y):""" 损失函数求导 """return y_pred.view_as(y) - ydef grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = grad_loss_fn(y_pred, y) * xgrad_b = grad_loss_fn(y_pred, y)return torch.cat((grad_w.mean(dim=0), grad_b.mean().unsqueeze(0)), 0)def model_training(x, y, n_epochs, learning_rate, params, print_params=True):""" 训练 """for epoch in range(1, n_epochs + 1):w, b = params[: -1], params[-1]# 前向传播y_pred = model(x, w, b)# 计算损失loss = loss_fn(y_pred, y)# 梯度grad = grad_fn(x, y, y_pred)# 更新参数params -= learning_rate * gradif epoch == 1 or epoch % 10 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))if print_params:print(f'参数:{params.detach().numpy()}')print(f'梯度:{grad.detach().numpy()}')return paramsdef generate_data():""" 随机生成数据 """np.random.seed(0)# 使用二个高斯分布来生成随机数据phi = 0.6means = [[0.0, -3.2], [1.0, 3.5]]covs = np.zeros((2, 2, 2))covs[0] = [[0.58, -0.05], [-0.05, 1.55]]covs[1] = [[0.65, -0.15], [-0.15, 1.12]]priors = [1 - phi, phi]n = 100x = np.zeros((n, 2))y = np.zeros((n, 1))# 选择一个高斯,并随机抽样数据for i in range(n):comp = np.random.choice(2, p=priors)x[i] = np.random.multivariate_normal(means[comp], covs[comp], 1)y[i] = compreturn torch.from_numpy(x).float(), torch.from_numpy(y).float()def plot_decision_boundary(x, y, theta):"""绘制二元分类问题的决策边界输入参数x:输入,y:输出,theta:参数输出参数无"""plt.figure()neg_x = x[np.where(y[:, 0] == 0)]pos_x = x[np.where(y[:, 0] == 1)]neg = plt.scatter(neg_x[:, 0], neg_x[:, 1], c='b', marker='o')pos = plt.scatter(pos_x[:, 0], pos_x[:, 1], c='r', marker='+')# 绘制决策边界# 只需要两点便可以定义一条直线,选择两个端点plot_x = np.array([min(x[:, 0]), max(x[:, 0])])# 计算决策边界线,theta0 + theta1*x + theta2*y = 0# 已知x,可计算yplot_y = np.dot(np.divide(-1, theta[1]), (theta[2] + np.dot(theta[0], plot_x)))lr, = plt.plot(plot_x, plot_y, 'g')  # 绘制拟合直线# 坐标plt.xlabel('x1')plt.ylabel('x2')# 图例plt.legend([neg, pos, lr], ['负例', '正例', u'决策边界'], loc='lower right')plt.show()def main():# 随机生成数据x, y = generate_data()# 模型参数初始化w = torch.zeros(2)b = torch.zeros(1)# 直接用未优化的模型来预测y_pred = model(x, w, b)print('未优化的模型的预测结果:', y_pred.detach().numpy())loss = loss_fn(y_pred, y)print('未优化的模型的损失:', loss.detach().numpy())params = model_training(x=x,y=y,n_epochs=500,learning_rate=0.1,params=torch.tensor([0.0, 0.0, 0.0]))print(f'梯度下降找到的w和b:{params.numpy()} \n')y_pred = model(x, params[: -1], params[-1])print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘制决策边界plot_decision_boundary(x, y, params)if __name__ == "__main__":main()

运行结果:
在这里插入图片描述

3)使用Pytorch实现逻辑回归模型

使用nn.Sequential定义模型;nn.Sigmoid定义激活函数。

创建文件logistic_regression_concise.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
简洁实现逻辑回归模型
"""
import torch
import torch.optim as optim
import torch.nn as nn
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
def model_training(x, y, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred = model(x)# 计算损失loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 10 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))def generate_data():""" 随机生成数据 """np.random.seed(0)# 使用二个高斯分布来生成随机数据phi = 0.6means = [[0.0, -3.2], [1.0, 3.5]]covs = np.zeros((2, 2, 2))covs[0] = [[0.58, -0.05], [-0.05, 1.55]]covs[1] = [[0.65, -0.15], [-0.15, 1.12]]priors = [1 - phi, phi]n = 100x = np.zeros((n, 2))y = np.zeros((n, 1))# 选择一个高斯,并随机抽样数据for i in range(n):comp = np.random.choice(2, p=priors)x[i] = np.random.multivariate_normal(means[comp], covs[comp], 1)y[i] = compreturn torch.from_numpy(x).float(), torch.from_numpy(y).float()def plot_decision_boundary(x, y, model):"""绘制二元分类问题的决策边界输入参数x:输入,y:输出,model:模型输出参数无"""plt.figure()neg_x = x[np.where(y[:, 0] == 0)]pos_x = x[np.where(y[:, 0] == 1)]neg = plt.scatter(neg_x[:, 0], neg_x[:, 1], c='b', marker='o')pos = plt.scatter(pos_x[:, 0], pos_x[:, 1], c='r', marker='+')# 绘制决策边界# 网格范围u = np.linspace(min(x[:, 0]), max(x[:, 0]), 150)v = np.linspace(min(x[:, 1]), max(x[:, 1]), 150)uu, vv = np.meshgrid(u, v)  # 生成网格数据z = model(torch.cat((torch.from_numpy(uu.ravel()).float().unsqueeze(1),torch.from_numpy(vv.ravel()).float().unsqueeze(1)), 1))# 保持维度一致z = z.detach().numpy().reshape(uu.shape)# 画图plt.contour(uu, vv, z, 0)# 坐标plt.xlabel('x1')plt.ylabel('x2')# 图例plt.legend([neg, pos], ['负例', '正例'], loc='lower right')plt.show()def main():# 随机生成数据x, y = generate_data()# 定义模型seq_model = nn.Sequential(nn.Linear(2, 1),nn.Sigmoid())# 打印模型信息print(seq_model)# 模型参数初始化print('\n使用SGD训练模型')learning_rate = 0.1# 使用optim模块中的现成优化器optimizer = optim.SGD(seq_model.parameters(), lr=learning_rate)model_training(x=x,y=y,n_epochs=500,optimizer=optimizer,model=seq_model,loss_fn=nn.BCELoss())print('优化后的模型参数')for name, param in seq_model.named_parameters():print(name, param)y_pred = seq_model(x)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘制决策边界plot_decision_boundary(x, y, seq_model)if __name__ == "__main__":main()

4.softmax回归

解决多元分类问题可以使用softmax回归。softmax回归的输出单元数k>2,对应k个类别的预测概率分布。训练好模型后,选择概率最大的类别作为预测类别。

1)介绍

思想:

1.假设函数,概率分布归一化

2.代价函数使用交叉熵

2)从头开始实现softmax回归

创建文件softmax_regression_from_scratch.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现softmax回归
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils import data
import numpy as np# 超参数
num_inputs = 784
num_outputs = 10def softmax(z):"""实现Softmax激活函数。每一个Z减去一个max值是为了避免数值溢出输入参数:z:二维Tensor数组返回:a:softmax(z)输出,与z的shape一致"""z_rescale = z - torch.max(z, dim=1, keepdim=True)[0]a = torch.exp(z_rescale) / torch.sum(torch.exp(z_rescale), dim=1, keepdim=True)assert (a.shape == z.shape)return adef model(x, w, b):""" 定义Softmax模型 """return softmax(torch.mm(x.view((-1, num_inputs)), w) + b)def cross_entropy(y_hat, y):""" 计算交叉熵 """return - torch.log(y_hat.gather(1, y.view(-1, 1)))def grad_loss_fn(y_pred, y):""" 损失函数求导 """return y_pred - torch.nn.functional.one_hot(y, num_classes=10)def grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = torch.mm(x.view((-1, num_inputs)).T, grad_loss_fn(y_pred, y))grad_b = grad_loss_fn(y_pred, y)return [grad_w, grad_b.mean(dim=0)]def accuracy(y_hat, y):""" 计算分类准确率 """_, pred_y = torch.max(y_hat, 1)return (pred_y == y).mean().item()def evaluate_accuracy(data_iter, net, w, b):""" 计算准确率 """correct_acc, n = 0.0, 0for x, y in data_iter:_, pred_y = torch.max(net(x, w, b).data, 1)correct_acc += (pred_y == y).sum().item()n += y.shape[0]return correct_acc / ndef train(net, train_iter, test_iter, loss, num_epochs, params, lr):""" 模型训练 """w, b = paramsfor epoch in range(num_epochs):train_loss_sum, train_acc_sum, n = 0.0, 0.0, 0for x, y in train_iter:# 前向传播y_pred = net(x, w, b)# 计算损失loss_mini_batch = loss(y_pred, y).sum()# 梯度grad = grad_fn(x, y, y_pred)# 更新参数for i in range(len(params)):params[i] -= lr * grad[i]# 统计train_loss_sum += loss_mini_batch.item()train_acc_sum += (y_pred.argmax(dim=1) == y).sum().item()n += y.shape[0]# 测试准确率test_acc = evaluate_accuracy(test_iter, net, w, b)print('轮次:%d,损失%.4f,训练准确率:%.3f,测试准确率:%.3f'% (epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc))def get_labels_by_indices(labels):""" 返回目标索引对应的标签字符串 """text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat', 'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def main():# 超参数num_epochs, learning_rate, batch_size = 5, 0.001, 32# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_iter = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_iter = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)# 参数w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_outputs)), dtype=torch.float, requires_grad=False)b = torch.zeros(num_outputs, dtype=torch.float, requires_grad=False)# 训练模型train(model, train_iter, test_iter, cross_entropy, num_epochs, [w, b], learning_rate)# 显示部分测试数据的真实标签和预测标签x, y = next(iter(test_iter))true_labels = get_labels_by_indices(y.numpy())pred_labels = get_labels_by_indices(model(x, w, b).argmax(dim=1).numpy())for true_label, pred_label in zip(true_labels, pred_labels):print(f"真实标签:{true_label}\t预测标签:{pred_label}")if __name__ == '__main__':main()
3)使用Pytorch实现softmax回归

使用Pytorch的自动求导功能。

创建文件softmax_regression.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
softmax回归实现
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
import torch.nn.functional as Fclass Net(nn.Module):""" 定义Softmax模型 """def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(784, 10)def forward(self, x):# 展平数据 (n, 1, 28, 28) --> (n, 784)x = x.view(-1, 784)return F.softmax(self.fc1(x), dim=1)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):# 每次输入batch_idx个数据loss_acc = 0.0  # 累计损失for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data)# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)model = Net()# 交叉熵损失函数loss_fn = nn.CrossEntropyLoss()# 优化算法optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)train(num_epochs, train_loader, model, optimizer, loss_fn, print_every)test(model, test_loader)if __name__ == '__main__':main()

运行结果:

轮次:1,损失0.6634,训练准确率:0.782,测试准确率:0.805
轮次:2,损失0.5175,训练准确率:0.826,测试准确率:0.817
轮次:3,损失0.4881,训练准确率:0.835,测试准确率:0.827
轮次:4,损失0.4720,训练准确率:0.840,测试准确率:0.830
轮次:5,损失0.4616,训练准确率:0.844,测试准确率:0.830
真实标签:ankle boot 预测标签:ankle boot
真实标签:pullover 预测标签:pullover
真实标签:trouser 预测标签:trouser
真实标签:trouser 预测标签:trouser
真实标签:shirt 预测标签:shirt
真实标签:trouser 预测标签:trouser
真实标签:coat 预测标签:coat
真实标签:shirt 预测标签:shirt
真实标签:sandal 预测标签:sandal
真实标签:sneaker 预测标签:sneaker
真实标签:coat 预测标签:coat
真实标签:sandal 预测标签:sandal
真实标签:sneaker 预测标签:sandal
真实标签:dress 预测标签:dress
真实标签:coat 预测标签:coat
真实标签:trouser 预测标签:trouser
真实标签:pullover 预测标签:pullover
真实标签:coat 预测标签:pullover
真实标签:bag 预测标签:bag
真实标签:t-shirt 预测标签:t-shirt
真实标签:pullover 预测标签:pullover
真实标签:sandal 预测标签:sneaker
真实标签:sneaker 预测标签:sneaker
真实标签:ankle boot 预测标签:sneaker
真实标签:trouser 预测标签:trouser
真实标签:coat 预测标签:pullover
真实标签:shirt 预测标签:shirt
真实标签:t-shirt 预测标签:t-shirt
真实标签:ankle boot 预测标签:ankle boot
真实标签:dress 预测标签:dress
真实标签:bag 预测标签:bag
真实标签:bag 预测标签:bag

5.神经网络

1)神经元

线性回归实际上就是一个线性神经元。多变量线性回归实现了加权求和计算。增加了激活函数的神经元直接称为神经元

2)激活函数
1.绘制Sigmoid激活函数

创建文件plot_sigmoid.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制Sigmoid激活函数"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)activation = torch.nn.Sigmoid()# Sigmoid激活函数
print(activation(torch.Tensor([-1., 0., 1.])))
y_vals = activation(torch.Tensor(x_vals))# 绘制Sigmoid激活函数图像
plt.plot(x_vals, y_vals, "r--", label="Sigmoid", linewidth=1.5)
plt.ylim([-0.5, 1.5])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:
在这里插入图片描述

2.绘制双曲正切Tanh激活函数

它是Sigmoid函数的变体,放大并平移

# -*- coding: utf-8 -*-
"""
绘制双曲正切Tanh激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)activation = torch.nn.Tanh()# 双曲正切激活函数
print(activation(torch.Tensor([-1., 0., 1.])))
y_vals = activation(torch.Tensor(x_vals))# 绘制Tanh激活函数图像
plt.plot(x_vals, y_vals, "r--", label="Tanh", linewidth=1.5)
plt.ylim([-1.5, 1.5])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:
在这里插入图片描述

3.绘制ReLU激活函数

创建文件display_olympics_freestyle100m.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制ReLU激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)relu = torch.nn.ReLU()
relu6 = torch.nn.ReLU6()# ReLU激活函数
print("ReLU: ", relu(torch.Tensor([-5., 5., 10.])))
y_relu = relu(torch.Tensor(x_vals))# ReLU-6激活函数
print("ReLU-6: ", relu6(torch.Tensor([-5., 5., 10.])))
y_relu6 = relu6(torch.Tensor(x_vals))# 绘制ReLU激活函数图像
plt.plot(x_vals, y_relu, "r:", label="ReLU", linewidth=1.5)
plt.plot(x_vals, y_relu6, "b-.", label="ReLU6", linewidth=1.5)
plt.ylim([-1, 8])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:

在这里插入图片描述

4.绘制LeakyReLU激活函数

创建文件display_olympics_freestyle100m.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制LeakyReLU激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)leaky_relu = torch.nn.LeakyReLU()
elu = torch.nn.ELU()# ReLU激活函数
print("Leaky ReLU: ", leaky_relu(torch.Tensor([-5., 5., 10.])))
y_leaky_relu = leaky_relu(torch.Tensor(x_vals))# ELU激活函数
print("ELU: ", elu(torch.Tensor([-5., 5., 10.])))
y_elu = elu(torch.Tensor(x_vals))# 绘制ReLU激活函数图像
plt.plot(x_vals, y_leaky_relu, "r:", label="Leaky ReLU", linewidth=1.5)
plt.plot(x_vals, y_elu, "b-.", label="ELU", linewidth=1.5)
plt.ylim([-1, 8])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:

在这里插入图片描述

5.softmax函数

主要用于神经网络最后一层,解决多元分类问题

6.选择正确的激活函数

中间层选ReLU;二元分类选Sigmoid;多元分类选Softmax函数;深层网络一般避免Tanh函数和Sigmoid函数;如果出现较多死亡神经元,用Leaky ReLU和ELU函数代替

3)神经网络原理

主要思想:

1.神经网络表示和结构;

2.前向传播;

3.代价函数:训练权重和偏置。一般采用交叉熵代价函数

4.BP算法:即反向传播算法。用于优化神经网络参数算法,推荐使用Pytorch的自动求导解决方案。

4)Pytorch实现神经网络

nn.Sequential定义一个简单的神经网络模型;

另一种方式是使用nn.Module定义神经网络。

两种方式实现如下,

创建文件neural_networks_initialization.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch定义神经网络及参数初始化
"""import torch
from torch import nn
from torch.nn import initnum_inputs, num_hiddens, num_outputs = 4, 5, 3# nn.Sequential定义一个简单的神经网络模型
seq_model = nn.Sequential(nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_outputs),nn.Softmax(dim=1),
)class Net(nn.Module):""" 定义一个简单的神经网络模型 """def __init__(self):super().__init__()self.fc1 = nn.Linear(num_inputs, num_hiddens)self.act1 = nn.ReLU()self.fc2 = nn.Linear(num_hiddens, num_hiddens)self.act2 = nn.ReLU()self.fc3 = nn.Linear(num_hiddens, num_outputs)self.act3 = nn.Softmax(dim=1)def forward(self, x):x = self.act1(self.fc1(x))x = self.act2(self.fc2(x))return self.act3(self.fc3(x))def weights_init(m):""" 初始化网络权重 """if isinstance(m, nn.Conv2d):init.normal_(m.weight.data)# init.xavier_normal_(m.weight.data)# init.kaiming_normal_(m.weight.data)  # 卷积层参数初始化m.bias.data.fill_(0)elif isinstance(m, nn.Linear):m.weight.data.normal_()  # 全连接层参数初始化def main():# 初始化for params in seq_model.parameters():init.normal_(params, mean=0, std=0.01)print("nn.Sequential定义的网络:")print(seq_model)for name, param in seq_model.named_parameters():print(name, param.shape)# 随机初始化输入xx = torch.randn(10, 4)y_hat = seq_model(x)print(y_hat)model = Net()# 网络参数初始化model.apply(weights_init)  # apply函数会递归搜索网络中的子模块并应用初始化print("nnn.Module定义的网络:")print(model)y_hat = model(x)print(y_hat)if __name__ == "__main__":main()
5)神经网络应用示例一

需求:FashionMNIST分类问题。

创建文件neural_networks_demo1.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch实现神经网络示例一
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
from torch.nn import initnum_inputs, num_hiddens, num_outputs = 784, 256, 10# nn.Sequential模型
net = nn.Sequential(nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_outputs),
)for params in net.parameters():init.normal_(params, mean=0, std=0.01)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):loss_acc = 0.0  # 累计损失# 每次输入第batch_idx批数据for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data.view(data.shape[0], -1))# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 模型测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images.view(images.shape[0], -1))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)# 交叉熵损失函数loss_fn = nn.CrossEntropyLoss()# 优化算法optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)# 训练与评估train(num_epochs, train_loader, net, optimizer, loss_fn, print_every)test(net, test_loader)if __name__ == '__main__':main()
6)神经网络应用示例二

示例二使用nn.Module定义网络模型

创建文件neural_networks_demo2.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch实现神经网络示例二
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
import torch.nn.functional as Fnum_inputs, num_hiddens, num_outputs = 784, 256, 10class Net(nn.Module):""" nn.Module定义网络模型 """def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(num_inputs, num_hiddens)self.fc2 = nn.Linear(num_hiddens, num_outputs)def forward(self, x):# 展平数据 (n, 1, 28, 28) --> (n, 784)x = x.view(x.shape[0], -1)x = F.relu(self.fc1(x))return F.log_softmax(self.fc2(x), dim=1)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):loss_acc = 0.0  # 累计损失# 每次输入第batch_idx批数据for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data)# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 模型测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)model = Net()# 负对数似然损失函数loss_fn = nn.NLLLoss()# 优化算法optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 训练与评估train(num_epochs, train_loader, model, optimizer, loss_fn, print_every)test(model, test_loader)if __name__ == '__main__':main()
7)两层神经网络解决异或问题
# -*- coding: utf-8 -*-
"""
两层神经网络解决异或问题
"""import torch
from torch import nndef main():# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 定义输入单元数、隐藏层单元数、输出层单元数n_in, n_h, n_out = 2, 2, 1# 创建XOR数据集x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])y = torch.tensor([[0.0], [1.0], [1.0], [0.0]])# 创建模型model = nn.Sequential(nn.Linear(n_in, n_h),nn.Sigmoid(),nn.Linear(n_h, n_out),nn.Sigmoid())# 损失函数criterion = nn.MSELoss()# 优化器optimizer = torch.optim.Adam(model.parameters(), lr=0.01)# 梯度下降for epoch in range(1, 1001):# 前向传播y_pred = model(x)# 计算损失loss = criterion(y_pred, y)if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t损失:{loss.item()}')# 梯度置零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()# 预测y_pred = model(x)print("输入为:\n{}".format(x))print('输出为:\n{}'.format(y_pred))if __name__ == "__main__":main()
8)Fizz Buzz神经网络实现
# -*- coding: utf-8 -*-
"""
Fizz Buzz神经网络实现
"""import numpy as np
import torchdef binary_encode(i, num_digits):""" 将输入的十进制i转换为位数是num_digits的二进制 """return np.array([i >> d & 1 for d in range(num_digits)])def fizz_buzz_encode(i):""" 将输入数字编码为标签 """if i % 3 == 0 and i % 5 == 0:return 3elif i % 5 == 0:return 2elif i % 3 == 0:return 1else:return 0def fizz_buzz_decode(i, encode):""" 解码为人类可读的输出 """return [str(i), "Fizz", "Buzz", "FizzBuzz"][encode]# 超参数
learning_rate = 0.05
epochs = 3000
batch_size = 128
num_digits = 10
num_hidden = 100# 构建训练集。使用101~1024作为训练数据
train_x = torch.tensor([binary_encode(i, num_digits) for i in range(101, 2 ** num_digits)]).float()
train_y = torch.tensor([fizz_buzz_encode(i) for i in range(101, 2 ** num_digits)]).long()
# 随机置乱
torch.manual_seed(123)
rand_idx = torch.randperm(len(train_y))
train_x = train_x[rand_idx, :]
train_y = train_y[rand_idx]# 定义网络模型
model = torch.nn.Sequential(torch.nn.Linear(num_digits, num_hidden),torch.nn.ReLU(),torch.nn.Linear(num_hidden, 4)
)# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 模型训练
model.train()
for epoch in range(epochs):for start in range(0, len(train_x), batch_size):end = start + batch_sizebatch_x = train_x[start:end]batch_y = train_y[start:end]y_hat = model(batch_x)loss = criterion(y_hat, batch_y)optimizer.zero_grad()loss.backward()optimizer.step()# 计算训练损失loss = criterion(model(train_x), train_y).item()print(f'Epoch:{epoch}\tLoss:{loss}')# 预测1~100
model.eval()
test_x = torch.tensor([binary_encode(i, num_digits) for i in range(1, 101)]).float()
test_y = torch.tensor([fizz_buzz_encode(i) for i in range(1, 101)]).long()
with torch.no_grad():pred_y = model(test_x)
predictions = zip(range(1, 101), list(pred_y.max(1)[1].data.tolist()))print("预测:", [fizz_buzz_decode(i, x) for (i, x) in predictions])
acc = np.sum(pred_y.max(1)[1].numpy() == np.array(test_y)) / len(test_y)
print("准确率:{:.2%}".format(acc))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/139876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过SD卡给某摄像头植入可控程序

0x01. 摄像头卡刷初体验 最近研究了手上一台摄像头的sd卡刷机功能,该摄像头只支持fat32格式的sd卡,所以需要先把sd卡格式化为fat32,另外微软把fat32限制了最大容量32G,所以也只能用不大于32G的sd卡来刷机。 这里使用32G的sd卡来…

基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码

基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于樽海鞘群算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于樽海鞘群优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…

vColorPicker与vue3-colorPicker——基于 Vue 的颜色选择器插件

文章目录 前言样例特点 一、使用步骤?1. 安装2.引入3.在项目中使用 vcolorpicker 二、选项三、事件四、问题反馈问题所在安装引入例子效果图 前言 vColorPicker——官网 vColorPicker——GitHub 样例 vColorPicker是基于 Vue 的一款颜色选择器插件,仿照…

【入门Flink】- 10基于时间的双流联合(join)

统计固定时间内两条流数据的匹配情况,需要自定义来实现——可以用窗口(window)来表示。为了更方便地实现基于时间的合流操作,Flink 的 DataStrema API 提供了内置的 join 算子。 窗口联结(Window Join) 一…

面向对象基础(以python语言为例)

1、定义一个类;实例化类的对象;调用类中的方法 #定义一个类 class Student:#类方法(即函数)def study(self,course_name):print(f学生正在学习{course_name})def play(self):print("xx学生正在玩游戏")#实例化&#xf…

从0到1实现一个前端监控系统(附源码)

目录 一、从0开始 二、上报数据方法 三、上报时机 四、性能数据收集上报 收集上报FP 收集上报FCP 收集上报LCP 收集上报DOMContentLoaded 收集上报onload数据 收集上报资源加载时间 收集上报接口请求时间 五、错误数据收集上报 收集上报资源加载错误 收集上报js错…

Linux下C++调用python脚本实现LDAP协议通过TNLM认证连接到AD服务器

1.前言 首先要实现这个功能,必须先搞懂如何通过C调用python脚本文件最为关键,因为两者的环境不同。本质上是在 c 中启动了一个 python 解释器,由解释器对 python 相关的代码进行执行,执行完毕后释放资源。 2 模块功能 2.1python…

Windows server 2008 R2 IIS搭建ASP网站教程

一、安装应用程序服务器 提示安装成功 二、添加角色服务asp 三、asp网站配置 放入源码 设置网站首页为index.asp: 设置应用程序池 四、设置网站目录属性 五、access数据库连接配置 Cd c:\Windows\System32\inetsrv appcmd list apppool /xml | appcmd set apppool /…

K9203 996920302 面向DNP3的网络安全解决方案

K9203 996920302 面向DNP3的网络安全解决方案 2014年ISA卓越技术创新奖获得者,超电子,3eTI的CyberFence工业防火墙解决方案提供强大加密和应用程序级深度数据包检测(DPI)功能。最近,3eTI为其CyberFence产品线增加了DNP3(分布式网络协议)支持…

SpringBoot Web开发

SpringBoot3-Web开发 SpringBoot的Web开发能力,由SpringMVC提供。 Web开发的三种方式 方式处理过程注意事项实现效果全自动直接编写控制逻辑全部使用自动给配置默认效果手自一体Configuration、 配置WebMvcConfigurer、 配置WebMvcRegistrations不要标注 EnableWeb…

【Linux】:静动态库

静动态库 一.静态库1.设计静态库2.生成静态库3.发布静态库4.使用静态库 二.动态库1.设计动态库2.生成和发布动态库3.使用 一.静态库 程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 静态库链接格式:libxxx.a(前缀是lib,后缀是…

基于安卓android微信小程序的四六级助手系统

项目介绍 随着我国教育需求不断增加,高校教育资源有限,教育经费相对不足的情况下,利用现代信息技术发展高等教育,不仅充分利用了优秀的教育资源,而且为更多的人提供接受高等教育的机会,同时这也是极大促进…

【Unity每日一记】“调皮的协程”,协程和多线程的区别在哪里

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:uni…

网络原理-UDP/TCP详解

一. UDP协议 UDP协议端格式 由上图可以看出,一个UDP报文最大长度就是65535. • 16位长度,表示整个数据报(UDP首部UDP数据)的最大长度(注意,这里的16位UDP长度只是一个标识这个数据报长度的字段&#xff0…

机器视觉目标检测 - opencv 深度学习 计算机竞赛

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…

单链表按位序与指定结点 删除

按位序删除(带头结点) #define NULL 0 #include<stdlib.h>typedef struct LNode {int data;struct LNode* next; }LNode, * LinkList;//按位序删除&#xff08;带头结点&#xff09; bool ListInsert(LinkList& L, int i, int& e) {if (i < 1)return false;L…

iPhone或在2024开放第三方应用商店。

iPhone或开放第三方应用商店&#xff0c;可以说这是一个老生常谈的话题。对于像是iOS这样封闭的系统来说&#xff0c;此前传出苹果可能开放侧载消息的时候&#xff0c;又有谁能信&#xff0c;谁会信&#xff1f; 如果是按照苹果自身的意愿&#xff0c;这种事情自然是不可能发生…

Antd React Form.Item内部是自定义组件怎么自定义返回值

在线演示https://stackblitz.com/edit/stackblitz-starters-xwtwyz?filesrc%2FSelfTreeSelect.tsx 需求 当我们点击提交,需要返回用户名和选中树的id信息,但是,我不关要返回树的id信息,还需要返回选中树的名称 //默认返回的 {userName:梦洁,treeInfo:leaf1-value } //但是需…

SpringBoot项目调用openCV报错:nested exception is java.lang.UnsatisfiedLinkError

今天在通过web项目调用openCV的时候提示如下错误&#xff1a; nested exception is java.lang.UnsatisfiedLinkError:org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/la如下图所示&#xff1a; 但是通过直接启动java main函数确正常&#xff0c;初步诊断和SpringBoot热加载…

55基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲(椒盐)噪声

基于matlab的1.高斯噪声2.瑞利噪声3.伽马噪声4.均匀分布噪声5.脉冲&#xff08;椒盐&#xff09;噪声五组噪声模型&#xff0c;程序已调通&#xff0c;可直接运行。 55高斯噪声、瑞利噪声 (xiaohongshu.com)