Pytorch基础教程:从零实现手写数字分类

文章目录

  • 1.Pytorch简介
  • 2.理解tensor
    • 2.1 一维矩阵
    • 2.2 二维矩阵
    • 2.3 三维矩阵
  • 3.创建tensor
    • 3.1 你可以直接从一个Python列表或NumPy数组创建一个tensor:
    • 3.2 创建特定形状的tensor
    • 3.3 创建三维tensor
    • 3.4 使用随机数填充tensor
    • 3.5 指定tensor的数据类型
  • 4.tensor基本运算
    • 4.1 ‌算术运算:
      • 4.1.1 ‌加法‌:
      • 4.1.2 ‌减法‌:
      • 4.1.3 ‌乘法‌(逐元素乘法,不是矩阵乘法):
      • 4.1.4 ‌除法‌:
      • 4.1.5 ‌幂运算‌:
    • 4.2 ‌‌矩阵运算:
      • 4.2.1 ‌‌矩阵乘法‌:
      • 4.2.2 ‌‌‌矩阵转置‌:
      • 4.2.3 ‌‌‌逐元素运算的广播机制:
    • 4.3 ‌‌‌‌统计运算:
      • 4.3.1 ‌‌‌‌求和‌:
      • 4.3.2 ‌‌‌‌平均值‌:
      • 4.3.3 ‌‌‌‌最大值和最小值‌:
    • 4.4 形状操作:
      • 4.4.1 ‌‌‌‌改变形状‌:
      • 4.4.2 ‌‌‌‌展平‌:
  • 5.理解神经网络
    • 5.1 什么是分类,什么是回归
      • 5.1.1 分类
      • 5.1.2 回归
    • 5.2 有什么函数可以实现分类和回归?答案:线性回归
      • 5.2.1 从二元一次方程组到Simple Linear Regression
      • 5.2.1 什么是线性关系(Linear Relationship)?
    • 5.3 线性回归到神经网络
      • 5.3.1 理解新模型 - 简易版神经网络
  • 6.定义网络结构
  • 7.整理数据集
  • 8.训练模型
  • 9.保存模型
  • 10.加载模型
  • 11.使用GPU加速
    • 11.1 要将model(model里面的参数w和b)从内存放到显存。
    • 11.2 把加载的数据从内存加载到显存
    • 11.3 只要将模型的数据,测试数据和训练数据加载到显存,自然会使用GPU进行处理。

1.Pytorch简介

‌PyTorch是一个开源的深度学习框架,由Facebook的人工智能研究院(FAIR)开发,并于2017年1月正式推出。‌ PyTorch以其灵活性和易用性著称,特别适合于深度学习模型的构建和训练。它基于Torch张量库开发,提供了动态计算图的功能,允许在运行时改变计算图,这使得模型构建更加灵活

2.理解tensor

Tensor 是PyTorch中最近本的数据结构,可以将其视为n维数组或者矩阵。n维矩阵在我们生活里非常常见。

2.1 一维矩阵

在这里插入图片描述
基本操作
在这里插入图片描述

2.2 二维矩阵

二维矩阵是一个表格,其中包含行和列。例如:
在这里插入图片描述
在这个矩阵中,
a11a 11 、a12a12 、a13a13 、a21a21 、a22a22 、a23a23 、a31a31 、a32a32 、a33a33 是矩阵的元素。第一个方括号内的元素属于第一行,第二个方括号内的元素属于第二行,第三个方括号内的元素属于第三行。

2.3 三维矩阵

三维矩阵可以看作是由多个二维矩阵组成的“矩阵的矩阵”,通常用于表示多维数据。例如,一个3x3x3的三维矩阵可以表示为:
在这里插入图片描述
在这个三维矩阵中,每一个二维矩阵(由方括号包围的部分)可以看作是一个“层”,整个三维矩阵由这些层组成。

3.创建tensor

3.1 你可以直接从一个Python列表或NumPy数组创建一个tensor:

import torch

# 从Python列表创建tensor
data = [[1, 2], [3, 4]]
tensor_from_list = torch.tensor(data)
print(tensor_from_list)

# 从NumPy数组创建tensor
import numpy as np
np_array = np.array(data)
tensor_from_np = torch.from_numpy(np_array)
print(tensor_from_np)

在这里插入图片描述

3.2 创建特定形状的tensor

你可以使用torch的内置函数来创建具有特定形状和值的tensor:

import torch

# 创建一个全为零的tensor,形状为(2, 3)
zeros_tensor = torch.zeros((2, 3))
print(zeros_tensor)

# 创建一个全为一的tensor,形状为(2, 3)
ones_tensor = torch.ones((2, 3))
print(ones_tensor)

# 创建一个未初始化的tensor,形状为(2, 3),其值可能是随机的
uninit_tensor = torch.empty((2, 3))
print(uninit_tensor)

# 创建一个具有指定值的tensor,所有元素都设为5,形状为(2, 3)
full_tensor = torch.full((2, 3), 5)
print(full_tensor)

在这里插入图片描述

3.3 创建三维tensor

要创建一个三维tensor,你只需指定三个维度的大小:

import torch

# 创建一个形状为(2, 3, 4)的三维tensor,所有元素都初始化为0
three_dim_tensor = torch.zeros((2, 3, 4))
print(three_dim_tensor)

3.4 使用随机数填充tensor

你还可以使用随机数来填充tensor:

import torch

# 创建一个形状为(2, 3)的tensor,其元素是从均匀分布[0, 1)中抽取的随机数
rand_tensor = torch.rand((2, 3))
print(rand_tensor)

# 创建一个形状为(2, 3)的tensor,其元素是从标准正态分布中抽取的随机数
randn_tensor = torch.randn((2, 3))
print(randn_tensor)


在这里插入图片描述

3.5 指定tensor的数据类型

在创建tensor时,你还可以指定其数据类型(dtype):

import torch

# 创建一个形状为(2, 3)的tensor,元素类型为浮点数(默认)
float_tensor = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print(float_tensor)
print(float_tensor.dtype)  # 输出: torch.float32

# 创建一个形状为(2, 3)的tensor,元素类型为整数
int_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.int32)
print(int_tensor)
print(int_tensor.dtype)  # 输出: torch.int32



在这里插入图片描述

4.tensor基本运算

4.1 ‌算术运算:

4.1.1 ‌加法‌:

import torch
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])
z = x + y  # 对应元素相加
print(z)  # 输出: tensor([5., 7., 9.])

4.1.2 ‌减法‌:

z = x - y  # 对应元素相减
print(z)  # 输出: tensor([-3., -3., -3.])

4.1.3 ‌乘法‌(逐元素乘法,不是矩阵乘法):

z = x * y  # 对应元素相乘
print(z)  # 输出: tensor([4., 10., 18.])

4.1.4 ‌除法‌:

z = x / y  # 对应元素相除
print(z)  # 输出: tensor([0.2500, 0.4000, 0.5000])

4.1.5 ‌幂运算‌:

z = x ** 2  # 每个元素求平方
print(z)  # 输出: tensor([1., 4., 9.])

4.2 ‌‌矩阵运算:

4.2.1 ‌‌矩阵乘法‌:

A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
C = torch.mm(A, B)  # 或者使用 A @ B 在PyTorch 1.0及以上版本
print(C)  # 输出: tensor([[19, 22], [43, 50]])

4.2.2 ‌‌‌矩阵转置‌:

A_t = A.t()
print(A_t)  # 输出: tensor([[1, 3], [2, 4]])

4.2.3 ‌‌‌逐元素运算的广播机制:

PyTorch支持广播机制,当两个tensor的形状不完全相同时,较小的tensor会自动扩展以匹配较大的tensor的形状,然后进行逐元素运算。

x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor(2.0)  # 这是一个标量,将被广播到与x相同的形状
z = x + y
print(z)  # 输出: tensor([3., 4., 5.])

4.3 ‌‌‌‌统计运算:

4.3.1 ‌‌‌‌求和‌:

sum_x = x.sum()  # 对所有元素求和
print(sum_x)  # 输出: tensor(6.)

4.3.2 ‌‌‌‌平均值‌:

mean_x = x.mean()  # 对所有元素求平均值
print(mean_x)  # 输出: tensor(2.)

4.3.3 ‌‌‌‌最大值和最小值‌:

max_x, _ = x.max()  # 返回最大值及其索引(这里只关心最大值)
min_x, _ = x.min()  # 返回最小值及其索引(这里只关心最小值)
print(max_x)  # 输出: tensor(3.)
print(min_x)  # 输出: tensor(1.)

4.4 形状操作:

4.4.1 ‌‌‌‌改变形状‌:

x_reshaped = x.view(-1, 1)  # 将x改变为列向量
print(x_reshaped)  # 输出: tensor([[1.], [2.], [3.]])

4.4.2 ‌‌‌‌展平‌:

x_flattened = x.flatten()  # 将x展平为一维数组
print(x_flattened)  # 输出: tensor([1., 2., 3.])

5.理解神经网络

在开始之前,我觉得有必要提个醒, 神经网络本质上是数学,但我们仅仅作为开发者,我们要做的事情是通过pytorch或类似的工具实现我们想要的功能,达到我们想要的目的。至于为什么里面的数学公式是这样子,为什么神经网络的架构是这样搭,为什么他这个结构这么好,我们根本不用去管里面的最底层机理。我们只需要知道这样子这样子就能达到效果,就可以了。我们不要被这些数学公式吓跑了。

5.1 什么是分类,什么是回归

‌分类和回归是机器学习中两种基本的预测方法,它们的核心区别在于预测的输出类型‌。

5.1.1 分类

分类,简单来说,就是给数据打上标签,预测它属于哪一个类别。比如,我们有一堆邮件,需要判断哪些是垃圾邮件,哪些是正常邮件。这就是一个典型的二分类问题,因为输出只有两种可能:垃圾邮件或正常邮件。再比如,我们有一张动物图片,需要判断它是猫、狗还是其他动物,这就是一个多分类问题,因为输出有多个可能的类别‌。

举例:想象你手里有一堆水果,你需要把它们分成苹果和橙子两类,这就是分类任务。你要看水果的颜色、形状等特征,然后决定它是苹果还是橙子。

5.1.2 回归

回归,则是预测一个具体的数值,这个数值可以是任何实数。比如,我们想知道一套房子的价格,根据它的面积、位置等特征来预测。这就是一个回归问题,因为输出是一个连续的数值,而不是一个类别标签。再比如,我们想预测明天的温度或者股票的价格,这些都是回归问题‌。

举例:想象你要预测一辆汽车的价格,你会考虑它的品牌、型号、年份、里程数等特征,然后给出一个具体的价格预测,比如10万元、15万元等,这就是回归任务。
图片转自‘人工智能教学实践’
上图转自‘人工智能教学实践’博客,我觉得这张图很好地解析什么是分类,什么是回归,预测天气的是分类,预测温度是多少,是回归。

5.2 有什么函数可以实现分类和回归?答案:线性回归

5.2.1 从二元一次方程组到Simple Linear Regression

初中时,我们通过两个点的坐标求解二元一次方程。例如:已知直线y = ax + b 经过点(1,1)和(3,2),求解a, b的值。
在这里插入图片描述

解法是将坐标值带入方程,得到一个二元一次方程组,并对其进行求解:

在这里插入图片描述
坐标图如下:
在这里插入图片描述
以上二元一次方程组的求解可以看作一个简单的线性回归问题,估算出x和y之间的线性关系,得到公式:y = 1/2*x + 1/2

5.2.1 什么是线性关系(Linear Relationship)?

在这里插入图片描述
在这里插入图片描述
需要注明的是,线性关系不仅仅指存在于两个变量之间,它也可以存在于三个或者更多变量之间。比如y = a + bx1 + cx2,这条直线可以在三维空间中表达。
但实际情况是,我们在真实世界的数据不会完美的落在一个直线上,即使两个数据存在线性关系,它们或多或少离完美的直线都还有一些偏差。图像表示如下:
在这里插入图片描述
以上直线表达的是predictor和outcome之间近似的线性关系:y ≈ ax + b

5.3 线性回归到神经网络

可以看出,线性回归非常直观且易于实现,同时也过于简单,只能适用于比较简单的模型,如果模型稍显复杂,则不能很好地反映数据的分布。
在这里插入图片描述
例如在该图中,红色线段为我们想要拟合的图形,蓝色线段为我们的线性回归模型,无论怎样调整斜率w 或截距 b,都无法与红色较好地匹配。说明在此例中,线性函数模型过于简单,我们需要一个稍微复杂一些的模型。这里我们引入一个分段函数作为模型:
在这里插入图片描述
可以看出,当 x<x1 或 x>x2 时,函数值恒等于一个值,而当 x∈[x1,x2] 时,函数值则是呈线性变化的。该函数图像如下:
在这里插入图片描述
所以如果用这个分段函数来模拟上面的红色线段的话,可以采用下面几个步骤:
在这里插入图片描述
step 0:取常数 b 作为红色线段在 y 轴上的截距;
step 1:令分段函数中间部分的斜率和长度与红色线段第一部分相同(w1,b1);
step 2:令分段函数中间部分的斜率和长度与红色线段第二部分相同(w2,b2);
step 3:令分段函数中间部分的斜率和长度与红色线段第三部分相同(w3,b3)。
所以红色线段可用几个不同的蓝色线段表示为:
在这里插入图片描述
问题又来了,这种分段函数看着非常复杂,而且计算不方便,能否再使用一个近似的函数进行替换呢?于是这里又引入了 Sigmoid 函数:
在这里插入图片描述
Sigmoid 函数可以很好的表现上面的蓝色线段,而且是非线性的,没有线性的那么直(或者说hard),所以也把上面蓝色的图形叫做hard sigmoid。
于是,我们的模型又等价于:
在这里插入图片描述
这里 n 的大小,取决于我们要模拟多复杂的函数,n越大,意味着要模拟的函数越复杂。
在这里插入图片描述

5.3.1 理解新模型 - 简易版神经网络

对于我们的新模型
在这里插入图片描述
来说,可以看做是先进行线性计算,然后放入Sigmoid函数计算后,再加上常数b的过程。可用下图表示:
在这里插入图片描述
如此一来,原本稍显繁琐的公式一下子就显得直观了不少。而且整个图看起来与神经网络非常相似,线性函数 wx+b 为输入层,Sigmoid 可看做隐藏层,加总后的y可看做输出层。如果让模型变得更复杂点,就更像了:
在这里插入图片描述
这里,我们增加了输入样本的复杂度(由单一连接变成了全连接),并且增加了多层 Sigmoid 函数,虽然模型整体更加复杂,但本质上还是没有变。所以我们完全可以从一个简单的线性模型过渡到一个复杂的神经网络。
再来看公式,看到这个加总符号 ∑,就说明里面进行的都是一系列相似的计算,所以用向量替换比较合适。
如果先约定好,统一使用列向量来表示数据,并使用 σ(x) 表示 Sigmoid 函数,则以上数据及参数可表示为:
在这里插入图片描述
然后我们就可以用这些向量来表示模型的公式了:
在这里插入图片描述

使用这种表示方式,不仅显得更简洁,而且计算速度也非常快,特别是当样本非常多的情况下。

6.定义网络结构

如果觉得上面讲解还是有点复杂,我们可以将神经网络简单粗暴地理解成是多对多的线性方程,比如说,我现在有个784像素的图片,图片里都是0-9的单独数字,想通过一张图片,预测是哪个数字。

输入: 784个参数
输出: 10个预测的概率

哪个概率最大哪个就是预测的数字。这就是我们要搭建的结构。
之前提过了, 一个神经网络中间是有几个隐藏层。而且隐藏层的参数个数我们可以自己定义,那上面的结构就可以这样表示。

输入: 784个参数
隐藏层1: 555个参数
隐藏层2: 888个参数
输出: 10个预测的概率

隐藏层的参数个数我们可以自己定义,这里隐藏层1参数个数我随便设置成555,隐藏层2参数个数设置成888.
但层与层之前的我们通过什么的方式连接呢?我们可以通过in_features, out_features的数值来设置,比如说这一层的输入的参数个数,是上一层的输出参数的个数, 这一层的输出的参数个数,是下一成的输入的参数个数。

输入: in_features = 784,out_features = 555
隐藏层1: in_features = 555,out_features = 888
隐藏层2: in_features = 888,out_features = 888
输出: in_features = 888,out_features = 10

到这里,大体的网络框架大概搭建了,但刚才说到了除了输入和输出外,我们还需要一个激活函数,激活函数我们之前学到了Sigmoid ,让线性的函数变得更加符合现实化,非线性化。也就是:

输入: in_features = 784,out_features = 555
激活函数: Sigmoid()
隐藏层1: in_features = 555,out_features = 888
激活函数: Sigmoid()
隐藏层2: in_features = 888,out_features = 888
激活函数: Sigmoid()
输出: in_features = 888,out_features = 10

到这里的话其实神经网络已经体现出来了,但这个输出的值是一个正无穷到负无穷的值。它还不是一个概率值。

比如: [[-0.0575, -0.0059, 0.0094, 0.0205, -0.0239, 0.0034, -0.0519, -0.0335, 0.0502, 0.0181]]

我们还需要对他进行归一化。我们会用到一个函数叫Softmax(), 这个函数的作用就是对这些正无穷到负无穷的值进行处理,使其变成0-1之间的数,变成0-1之间的数后,我们就可以大胆地称之为概率。
在这里插入图片描述
在这里插入图片描述
ok, 那经过上面的套路,总结起来,神经网络就是

输入: in_features = 784,out_features = 555
激活函数: Sigmoid()
隐藏层1: in_features = 555,out_features = 888
激活函数: Sigmoid()
隐藏层2: in_features = 888,out_features = 888
激活函数: Sigmoid()
输出: in_features = 888,out_features = 10
归一化: Softmax()

到此为止,我们已经手撕了一个简单的神经网络,回到我们的主题,如何通过Pytorch搭建神经网络。Here we go!

import torch
import torch.nn as nn

#784个像素点构成的灰度图->函数->10个概念(0,1,2,3,4,5,6,7,8,9)


#输入层 in_channel=784 out_channel=555
#隐藏层1 in_channel=555 out_channel=888
#隐藏层2 in_channel=888 out_channel=888
#输出层 in_channel=888 out_channel=10

data = torch.rand(1, 784)

model = nn.Sequential(
    nn.Linear(784, 555),
    nn.Sigmoid(),
    nn.Linear(555, 888),
    nn.Sigmoid(),
    nn.Linear(888, 888),
    nn.Sigmoid(),
    nn.Linear(888, 10),
    nn.Softmax()
)

predict = model(data)
print(model)
print(predict)

在这里插入图片描述
Pytorch已经帮我们封装好了函数,我们更重要的是理解然后手撕了一个简单的神经网络,然后通过Pytorch提供的函数进行调用了完事了。

7.整理数据集

我们可以从kaggle比赛中下载数据集。
https://www.kaggle.com/competitions/digit-recognizer/data

在这里插入图片描述
在这里插入图片描述
又或者到我的CSDN资源直接下载: kaggle手写数字识别竞赛中用到的数据集


下载完后,我们主要来看train.csv
在这里插入图片描述
从train.csv可以看到,第一列是标签, 其他列就是像素,0,1,2。。。。783
我们需要python中pandas的工具包来帮我们分解train.csv,并且用来隔开特征和标签。

import pandas as pd

raw_df = pd.read_csv('dataset/train.csv')
# 标签
label = raw_df['label'].values
# 特征
feature = raw_df.drop(['label'], axis=1)

特征这一列中,我们先删除label这一列,然后保留其他列,剩下的就是特征。
分割完标签和特征后,我们还要分测试集和训练集。我采取4:1的分割方式。

import torch
import torch.nn as nn
import pandas as pd

raw_df = pd.read_csv('dataset/train.csv')
# 标签
label = raw_df['label'].values
# 特征
feature = raw_df.drop(['label'], axis=1).values


#整个数据集划分成两个数据集 训练集 测试集, 4:1

train_feature = feature[:int(len(feature)*0.8)]
train_label = label[:int(len(label)*0.8)]
test_feature = feature[int(len(feature)*0.8):]
test_label = label[int(len(label)*0.8):]

print(len(train_feature),len(train_label),len(test_feature),len(test_label))

打印结果

33600 33600 8400 8400

至此,数据准备完成。

8.训练模型

模型架构有了, 数据也准备好了,我们可以训练起来了。
说到训练,我们就要进行梯度下降。找到一组合适的w和b,让损失值越小越好。
优先我们要准备一个损失函数,交叉熵损失函数。用来计算损失值。

lossfunction = nn.CrossEntropyLoss()

计算完损失值,我们下一步就是优化里面的w和b, pytorch给我们提供了很多优化函数,我们用Adam就足够了。

optimizer = torch.optim.Adam(params=model.parameters(), lr=0.0001)

import torch
import torch.nn as nn
import pandas as pd

raw_df = pd.read_csv('dataset/train.csv')
# 标签
label = raw_df['label'].values
# 特征
feature = raw_df.drop(['label'], axis=1).values


#整个数据集划分成两个数据集 训练集 测试集, 4:1

train_feature = feature[:int(len(feature)*0.8)]
train_label = label[:int(len(label)*0.8)]
test_feature = feature[int(len(feature)*0.8):]
test_label = label[int(len(label)*0.8):]

train_feature = torch.tensor(train_feature).to(torch.float)
train_label = torch.tensor(train_label)
test_feature = torch.tensor(test_feature).to(torch.float)
test_label = torch.tensor(test_label)

print(len(train_feature),len(train_label),len(test_feature),len(test_label))


#784个像素点构成的灰度图->函数->10个概念(0,1,2,3,4,5,6,7,8,9)


#输入层 in_channel=784 out_channel=555
#隐藏层1 in_channel=555 out_channel=888
#隐藏层2 in_channel=888 out_channel=888
#输出层 in_channel=888 out_channel=10

data = torch.rand(1, 784)

model = nn.Sequential(
    nn.Linear(784, 555),
    nn.Sigmoid(),
    nn.Linear(555, 888),
    nn.Sigmoid(),
    nn.Linear(888, 888),
    nn.Sigmoid(),
    nn.Linear(888, 10),
    nn.Softmax()
)

# predict = model(data)
# print(model)
# print(predict)

# 梯度下降。找到一组合适的w和b,让损失值越小越好。
lossfunction = nn.CrossEntropyLoss()
# 优化器
optimizer = torch.optim.Adam(params=model.parameters(), lr=0.0001)


# 训练的轮数
for i in range(100):
    # 清空优化器的梯度(偏导)
    optimizer.zero_grad()
    predict = model(train_feature)
    loss = lossfunction(predict, train_label)
    loss.backward()
    optimizer.step()
    print(loss.item())

至此,简单的神经网络训练程序已经搭建出来了, 我们可以开始运行,打印损失值。
在这里插入图片描述
我们可以看到损失值越来越小。意味着我们预测的准确率越来越高。
其实到这里我们已经结束了,但我们还想看看准确率,那我们可以在中间打印一下。首先

predict = model(train_feature)

这个predict 是一个数组,是包含所有概率的数组,我们简单理解成这样的数据。

0.3,0.1,0.2,0.1,0.0,0.0,0.0,0.0,0.0,0.0
0.1,0.1,0.2,0.1,0.0,0.0,0.0,0.0,0.5,0.0
0.2,0.1,0.2,0.1,0.0,0.0,0.0,3.0,0.3,0.0
0.1,0.1,0.2,0.1,0.0,0.0,0.0,0.1,0.0,0.0
0.1,0.1,0.2,0.1,0.0,0.0,0.0,0.3,0.0,0.0

我们首先要是每一行里面找到最大值,然后拿出它对应的数字,这里的数字其实就是对应的索引

result = torch.argmax(predict, axis=1)

然后准确率我们可以用这个result和train_label进行对比

train_acc = torch.mean((result==train_label).to(torch.float))

打印结果再看看

# 训练的轮数
for i in range(100):
    # 清空优化器的梯度(偏导)
    optimizer.zero_grad()
    predict = model(train_feature)
    result = torch.argmax(predict, axis=1)
    train_acc = torch.mean((result == train_label).to(torch.float))
    loss = lossfunction(predict, train_label)
    loss.backward()
    optimizer.step()
    print('train loss:{} train acc:{}'.format(loss.item(), train_acc.item()))

在这里插入图片描述

损失值越来越小,准确率越来越高,这就是我们想要的结果。

9.保存模型

torch.save(model.state_dict(), '/mymodel.pt')

就这么简单。model.state_dict()就是训练完的w和b, '/mymodel.pt’就是要保存的路径和名称。

10.加载模型

这里我新建了一个python文件check_model.py

parameters = torch.load('/mymodel.pt')

先拿到之前模型的参数。
但我们要先把之前定义的网络结构搬回来。

model = nn.Sequential(
    nn.Linear(784, 555),
    nn.Sigmoid(),
    nn.Linear(555, 888),
    nn.Sigmoid(),
    nn.Linear(888, 888),
    nn.Sigmoid(),
    nn.Linear(888, 10),
    nn.Softmax()
)

然后再将参数塞进model

model.load_state_dict(parameters)

然后我们再用pandas加载数据, 拿出对应的标签和我们预测的值进行对比。

import torch
import torch.nn as nn
import pandas as pd

model = nn.Sequential(
    nn.Linear(784, 555),
    nn.Sigmoid(),
    nn.Linear(555, 888),
    nn.Sigmoid(),
    nn.Linear(888, 888),
    nn.Sigmoid(),
    nn.Linear(888, 10),
    nn.Softmax()
)

parameters = torch.load('/mymodel.pt')

model.load_state_dict(parameters)


raw_df = pd.read_csv('dataset/train.csv')
# 标签
label = raw_df['label'].values
# 特征
feature = raw_df.drop(['label'], axis=1).values
test_feature = feature[int(len(feature)*0.8):]
test_label = label[int(len(label)*0.8):]
test_feature = torch.tensor(test_feature).to(torch.float)
test_label = torch.tensor(test_label)

new_test_feature = test_feature[100:111]
new_test_label = test_label[100:111]

predict = model(new_test_feature)
result = torch.argmax(predict, axis=1)
print(new_test_label)
print(result)

在这里插入图片描述
预测结果正常,有六个预测正确,因为之前的trainning里面只有0.5左右的正确率,有可能训练的次数有关,训练次数太少。所以这个结果符合我们预期。

11.使用GPU加速

有人会问,我们已经装好了GPU版本的pytorch,为什么还要GPU加速。因为我们默认是用CPU运行,我们需要对代码再进行GPU调用。
使用GPU加速主要可以用两个方向,model方向和数据方向

11.1 要将model(model里面的参数w和b)从内存放到显存。

model = model.cuda() 

11.2 把加载的数据从内存加载到显存

train_feature = torch.tensor(train_feature).to(torch.float).cuda() 
train_label = torch.tensor(train_label).cuda() 
test_feature = torch.tensor(test_feature).to(torch.float).cuda() 
test_label = torch.tensor(test_label).cuda() 

11.3 只要将模型的数据,测试数据和训练数据加载到显存,自然会使用GPU进行处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

git操作(bitbucket仓库)

在代码远程版本控制和提交过程中需要经常使用git命令&#xff0c;熟练使用git是一个软件工程师必备的技能之一。 将主版本代码fork到自己的 bitbucket 子仓库中 克隆到本地 利用ssh链接进行克隆&#xff0c;将 fork 的子仓库克隆到本地。 git clone ssh://{$你fork的子bitbu…

【AIGC】SYNCAMMASTER:多视角多像机的视频生成

标题&#xff1a;SYNCAMMASTER: SYNCHRONIZING MULTI-CAMERA VIDEO GENERATION FROM DIVERSE VIEWPOINTS 主页&#xff1a;https://jianhongbai.github.io/SynCamMaster/ 代码&#xff1a;https://github.com/KwaiVGI/SynCamMaster 文章目录 摘要一、引言二、使用步骤2.1 TextT…

登录系统网址作业

目录 主页代码 主页​编辑 效果1 登录页面代码 登录页面 效果2 注册页面代码 注册页面 效果3 主页代码 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content&qu…

[Do374]Ansible一键搭建sftp实现用户批量增删

[Do374]Ansible一键搭建sftp实现用户批量增删 1. 前言2. 思路3. sftp搭建及用户批量新增3.1 配置文件内容3.2 执行测试3.3 登录测试3.4 确认sftp服务器配置文件 4. 测试删除用户 1. 前言 最近准备搞一下RHCA LV V,外加2.9之后的ansible有较大变化于是练习下Do374的课程内容. 工…

00_专栏《Redis 7.x企业级开发实战教程》介绍

大家好,我是袁庭新。Redis作为一款高性能、多用途的内存数据库,凭借其丰富的数据结构、高速读写能力、原子操作特性及发布订阅等功能,在缓存加速、分布式锁、消息队列等场景中不可或缺,极大提升了系统性能与开发效率,是现代互联网应用架构的关键组件。 你是否在学习Redis…

wow-agent 学习笔记

wow-agent-课程详情 | Datawhale 前两课比较基础&#xff0c;无笔记 第三课 阅卷智能体这一块&#xff0c;曾经做过一点和AI助教相关的内容&#xff0c;也是用了一个prompt去进行CoT&#xff0c;但是风格和课程中的不太相同&#xff0c;在下面附上我的prompt 你是一名资深教…

如何优化Elasticsearch大文档查询?

记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的&#xff0c;各种闸口数据及产品数据都是存储在ES的(有的是独立索引&#xff0c;有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…

idea分支合并代码

步骤一 首先把两个分支的代码都提交了&#xff0c;保持和远程仓库一致&#xff0c;不要有任何没提交的代码。如果一些程序的yml配置文件&#xff0c;不想提交&#xff0c;可以复制一个&#xff0c;不受git管理。如果有没有提交的代码&#xff0c;合并分支的时候就会提示那些代…

EasyLine(v2.0)自制光谱、曲线处理软件

前言&#xff1a;因为这次更新对软件的整体变动较大&#xff0c;所以就没有取版本v1.1&#xff0c;而是直接使用v2.0版本。然后上一版的讲解也不是很清楚&#xff0c;这次也做重点讲解一下。 自制光谱、曲线处理软件-EasyLine 软件的安装软件的使用总体介绍文件格式处理的使用 …

使用JMeter模拟多IP发送请求!

你是否曾遇到过这样的场景&#xff1a;使用 JMeter 进行压力测试时&#xff0c;单一 IP 被服务器限流或者屏蔽&#xff1f;这时&#xff0c;如何让 JMeter 模拟多个 IP 发送请求&#xff0c;成功突破测试限制&#xff0c;成为测试工程师必须攻克的难题。今天&#xff0c;我们就…

python如何设计矩阵

python设计矩阵&#xff1a; 1、调用numpy模块创建矩阵并设置矩阵的行跟列 import numpy matrix numpy.array([[1,2,3],[4,5,6],[7,8,9]])#创建矩阵 2、通过下标的办法输出二维列表中的一维列表&#xff0c;达到输出矩阵的效果 vector numpy.array([[1,2,3],[4,5,6],[7,8,9]…

量子计算:从薛定谔的猫到你的生活

文章背景 说到量子计算&#xff0c;不少人觉得它神秘又遥不可及。其实&#xff0c;它只是量子物理学的一个“应用小分支”。它的核心在于量子比特的“叠加”和“纠缠”&#xff0c;这些听上去像科幻小说的概念&#xff0c;却为计算世界开辟了一片全新的天地。如果经典计算是“…

python 轮廓 获取环形区域

目录 效果图&#xff1a; 代码&#xff1a; 效果图&#xff1a; 代码&#xff1a; import cv2 import numpy as np# 读取图像 image cv2.imread(rE:\project\jijia\tools_jijia\img_tools\ground_mask.jpg, cv2.IMREAD_GRAYSCALE) # 二值化图像 # 二值化图像 _, binary cv…

Python | 使用Matplotlib进行图案填充和边缘颜色分离的三种方法

Matplotlib是Python中功能强大的绘图库&#xff0c;允许广泛的自定义选项。一个常见的要求是分离出图中的图案填充和边缘颜色。默认情况下&#xff0c;Matplotlib中的填充颜色与边缘颜色相关联&#xff0c;但有一些方法可以独立自定义这些颜色。本文将深入研究如何实现这一点的…

OpenStack 网络服务的插件架构

OpenStack 的网络服务具有灵活的插件架构&#xff0c;可支持多种不同类型的插件以满足不同的网络需求。以下是对 OpenStack 网络服务插件架构中一些常见插件类型的介绍&#xff1a; 一、SDN 插件 Neutron 与 SDN 的集成&#xff1a;在 OpenStack 网络服务里&#xff0c;SDN 插…

从 MySQL 到 ClickHouse 的迁移与优化——支持上亿级数据量的复杂检索

文章目录 1. ClickHouse 背景与使用场景1.1 ClickHouse 简介1.2 ClickHouse 的特点1.3 ClickHouse 的使用场景 2. 从 MySQL 到 ClickHouse 的迁移2.1 MySQL 与 ClickHouse 的对比2.2 迁移背景2.3 迁移注意事项2.3.1 数据模型设计2.3.2 数据迁移2.3.3 SpringBoot 项目改造2.3.4 …

08:软件定时器+中断管理

软件定时器中断管理 1、软件定时器2、中断管理2.1、中断屏蔽2.2、临界区 1、软件定时器 软件定时器是基于 FreeRTOS 内核提供的时间管理功能实现的&#xff0c;允许开发者创建、启动、停止、删除和管理定时器&#xff0c;从而实现在任务中对时间的灵活控制。 软件定时器硬件定…

数据结构《MapSet哈希表》

文章目录 一、搜索树1.1 定义1.2 模拟实现搜索 二、Map2.1 定义2.2 Map.Entry2.3 TreeMap的使用2.4 Map的常用方法 三、Set3.1 定义3.2 TreeSet的使用3.3 Set的常用方法 四、哈希表4.1 哈希表的概念4.2 冲突4.2.1 冲突的概念4.2.2 冲突的避免1. 选择合适的哈希函数2. 负载因子调…

蓝桥与力扣刷题(709 转换成小写字母)

题目&#xff1a;给你一个字符串 s &#xff0c;将该字符串中的大写字母转换成相同的小写字母&#xff0c;返回新的字符串。 示例 1&#xff1a; 输入&#xff1a;s "Hello" 输出&#xff1a;"hello"示例 2&#xff1a; 输入&#xff1a;s "here…

unity学习16:unity里向量的计算,一些方法等

目录 1 unity里的向量&#xff1a; 2 向量加法 2.1 向量加法的几何意义 2.2向量加法的标量算法 3 向量减法 3.1 向量减法的几何意义 3.2 向量减法的标量算法 4 向量的标量乘法 5 向量之间的乘法要注意是左乘 还是右乘 5.1 注意区别 5.2 向量&#xff0c;矩阵&#x…