pytorch快速入門——手寫數字分類GPU加速

👑主頁:吾名招財
👓簡介:工科學碩,研究方向機器視覺,愛好較廣泛…
?💫簽名:面朝大海,春暖花開!

pytorch快速入門——手寫數字分類GPU加速

  • 一、tensor
    • 1,理解tensor
      • (1)一維矩陣(向量)
      • (2)二維矩陣(單通道灰度圖像)
      • (3)三維矩陣(彩色三通道圖像)
    • 2,創建tensor
      • (1)導入pytorch庫
      • (2)創建一維矩陣
      • (3)創建兩行四列的二維矩陣
      • (4)生成兩行五列的隨機矩陣
      • (5)生成兩行五列全為1的隨機矩陣
      • (6)生成兩行五列全為0的隨機矩陣
    • 3,tensor基本屬性
      • (1)形狀shape
      • (2)數據類型dtype
      • (3)轉換數據類型data.to()
    • 4,tensor的基本操作
      • (1)通過下標獲取對應的值(data[0][4].item())
      • (2)加減乘除運算(+ - * /)
      • (3)求所有值的和torch.sum()
      • (4)求平均值torch.mean()
      • (5)索引排序torch.argsort()
      • (6)最小值最大值索引(argmin,argmax)
      • (7)變形操作(如將其2行8列變成8行2列等)
  • 二、理解神經網絡
    • 1,分類、回歸、聚類
      • (1)分類
      • (2)回歸
      • (3)聚類
    • 2,區分貓狗
      • (1)差異計算
      • (2)線性分類
      • (3)softmax
      • (4)損失函數
      • (5)梯度下降
      • (6)非線性分類
      • (7)激活函數
      • (8)預測
      • (9)訓練
  • 三、手寫數字分類
    • 1,定義網絡結構
    • 2,整理數據集
    • 3,訓練模型
    • 4,勘誤
    • 5,保存模型
    • 6,加載模型并預測
    • 7,使用GPU加速

一、tensor

1,理解tensor

Tensor就是一個N維矩陣

(1)一維矩陣(向量)

在這里插入圖片描述

(2)二維矩陣(單通道灰度圖像)

二維矩陣:單通道圖像,Excel數據等
在這里插入圖片描述

(3)三維矩陣(彩色三通道圖像)

在這里插入圖片描述

2,創建tensor

create_tensor.py

(1)導入pytorch庫

import torch
print(torch.cuda.is_available())

(2)創建一維矩陣

#一維向量
data = torch.tensor([1,2,3,4])
print(data)#tensor([1, 2, 3, 4])

(3)創建兩行四列的二維矩陣

#兩行四列的二維矩陣
data = torch.tensor([[1,2,3,4],[2,3,4,5]])
print(data)# tensor([[1, 2, 3, 4],
#         [2, 3, 4, 5]])

(4)生成兩行五列的隨機矩陣

#生成兩行五列的隨機矩陣
data = torch.randn(2, 5)
print(data)
# tensor([[ 1.4212,  0.0784, -1.0818, -0.6843,  0.9947],
#         [-1.3718,  0.9556,  1.1089, -0.8161, -0.2081]])

(5)生成兩行五列全為1的隨機矩陣

#生成兩行五列全是一的矩陣
data = torch.ones(2, 5)
print(data)
# tensor([[1., 1., 1., 1., 1.],
#         [1., 1., 1., 1., 1.]])

(6)生成兩行五列全為0的隨機矩陣

#生成兩行五列全是0的矩陣
data = torch.zeros(2, 5)
print(data)
# tensor([[0., 0., 0., 0., 0.],
#         [0., 0., 0., 0., 0.]])#tensor中非常重要的一些屬性
data = torch.zeros(2, 5)

3,tensor基本屬性

(1)形狀shape

#1,形狀
print(data.shape)
# torch.Size([2, 5])
print(data.shape[0],data.shape[1])  #2 5   (兩行五列)

(2)數據類型dtype

#2,數據類型默認float32
print(data.dtype)
#torch.float32

(3)轉換數據類型data.to()

#更改數據類型
data = data.to(torch.int)
print(data)
# tensor([[0, 0, 0, 0, 0],
#         [0, 0, 0, 0, 0]], dtype=torch.int32)
print(data.dtype)
# torch.int32

4,tensor的基本操作

(1)通過下標獲取對應的值(data[0][4].item())

import torch#通過下標獲取對應的值
data = torch.tensor([[1,2,3,4,5],[2,3,4,5,6]])
data = data.to(torch.int)
print(data)
print(data.dtype)
#拿到第0行4列的值(但還是tensor類型的)
print(data[0][4])
# tensor(5, dtype=torch.int32)
#將tensor轉成真正要的數據
print(data[0][4].item())    #5

(2)加減乘除運算(+ - * /)

#加法運算,對應位置相加
data_a = torch.ones([3,3])
data_b = torch.zeros([3,3])
print(data_a+data_b)    #加完 后還是1data_a = torch.ones([3,3])
data_b = torch.tensor([[1,2,3],[2,3,4],[3,4,5]])
print(data_a+data_b)    #加完
# tensor([[2., 3., 4.],
#         [3., 4., 5.],
#         [4., 5., 6.]])print(data_a-data_b)
# tensor([[ 0., -1., -2.],
#         [-1., -2., -3.],
#         [-2., -3., -4.]])print(data_a*data_b)
# tensor([[1., 2., 3.],
#         [2., 3., 4.],
#         [3., 4., 5.]])print(data_a/data_b)
# tensor([[1.0000, 0.5000, 0.3333],
#         [0.5000, 0.3333, 0.2500],
#         [0.3333, 0.2500, 0.2000]])print(data_a/3)
# tensor([[0.3333, 0.3333, 0.3333],
#         [0.3333, 0.3333, 0.3333],
#         [0.3333, 0.3333, 0.3333]])

(3)求所有值的和torch.sum()

#求所有的值的和
data_b = torch.tensor([[1,2,3],[2,3,14],[3,4,25]])
print(torch.sum(data_b))
# tensor(27)# 1   2   3
# 2   3   14
# 3   4   25
print(torch.sum(data_b,axis=0)) #axis=0表示豎著相加
# tensor([ 6,  9, 42])
print(torch.sum(data_b,axis=1)) #axis=1表示橫著相加
# tensor([ 6, 19, 32])

(4)求平均值torch.mean()

#求平均值(輸入類型必須為浮點型或者復數)
print(torch.mean(data_b.to(torch.float),axis=1))
# tensor([ 2.0000,  6.3333, 10.6667])#
#假設下方為模型預測的結果
predict = torch.tensor([1,0,1,0,2,0,1,0,1,2])
#假設下方為標簽即所知的標準答案
label = torch.tensor([0,1,1,0,0,0,1,0,2,2])
#這里計算一下預測出來的東西和標準答案之間有多少是重合的
#判斷大于號
print(predict > label)
#tensor([ True, False, False, False,  True, False, False, False, False, False])
#判斷等于號是否為真
print(predict == label)
# tensor([False, False,  True,  True, False,  True,  True,  True, False,  True])
#查看10個中總共對了幾個(True認為1,Flase認為0)
print(torch.sum(predict == label))
#tensor(6)   總共6個是預測值與標簽相等的#使用mean來求其準確率
print(torch.mean((predict == label).to(torch.float)).item())
#0.6000000238418579

(5)索引排序torch.argsort()

#argsort將tensor值中從小到大的排序的索引拿到
data = torch.tensor([1,2,3,0,9,8,-1,-10])print(torch.argsort(data))
# tensor([7, 6, 3, 0, 1, 2, 5, 4])

(6)最小值最大值索引(argmin,argmax)

#數據中最小的值的索引得到
print(torch.argmin(data))
# tensor(7)
#數據中最大的值的索引得到
print(torch.argmax(data))
# tensor(4)#arg也可以接受軸的概念
data = torch.tensor([[1,2,3,0,9,8,-1,-10],[5,2,3,6,9,8,11,-10]])
print(torch.argmax(data, axis=0))
# tensor([1, 0, 0, 1, 0, 0, 1, 0])  #第一列5大,5是索引1。

(7)變形操作(如將其2行8列變成8行2列等)

##最后說一個操作變形
data = data.view(8,2) #將其2行8列變成8行兩列
print(data)
# tensor([[  1,   2],
#         [  3,   0],
#         [  9,   8],
#         [ -1, -10],
#         [  5,   2],
#         [  3,   6],
#         [  9,   8],
#         [ 11, -10]])##最后說一個操作變形
data = data.view(8,-1) #第2列寫個-1表示根據8行自動推斷有多少列
print(data)##最后說一個操作變形
data = data.view(-1,2) #第1列寫個-1表示根據2列自動推斷有多少行
print(data)#將二維矩陣變為一個向量,直接-1即可
data = data.view(-1)
print(data)
# tensor([  1,   2,   3,   0,   9,   8,  -1, -10,   5,   2,   3,   6,   9,   8,
#          11, -10])

二、理解神經網絡

1,分類、回歸、聚類

神經網絡、深度學習本質上就是數學再加上玄學

但我們僅僅是個開發者,我們要做的就是使用知名的框架如pytorch等來實現功能

至于里面的數學公式、神經網絡結構為什么這樣,最底層的機理暫時不用管,只要知道這樣,這樣 就能達到這樣的效果即可

什么是分類、什么是回歸、什么是聚類,這些都是機器學習或者深度學習中最簡單的任務了

左邊這些就是數據,右側就是結果

閱片無數的宅男(看做是神經網絡、模型)

(1)分類

對離散值的預測就是分類
在這里插入圖片描述

(2)回歸

對連續值的預測就是回歸

顏值打分神器

在這里插入圖片描述

(3)聚類

還是閱片無數的宅男,但是記性不太好,不認識這些人,潛移默化的將這些照片歸類,會發現好看的在一類,不好看的一類

但是不知道這個類別叫什么,也不知道 這個類別叫什么,這種任務就是聚類

分類與聚類都是把數據進行區分,但是最大的一個區別就是聚類中的數據是沒有所謂的標簽的

在這里插入圖片描述

2,區分貓狗

(1)差異計算

在這里插入圖片描述

把兩張圖片的像素矩陣算一個差異程度,算完差異度后跟誰的差異度最小就是那個類別

區分是貓還是狗
在這里插入圖片描述

(2)線性分類

更好的解決方案線性分類
假設有個函數,f()

x就是像素值,W、b
是函數中的參數,如果W、b確定了,隨便一張圖x進來都能給這張圖算出一個結果,結果表示 如下方右側

這個函數能分出10類

在這里插入圖片描述

在這里插入圖片描述

437.9是這里面最大的,所以這張圖就是狗,如果w、b比較厲害的話,那么隨便哪個都能預測的準確

(3)softmax

得到了得分,分數越高代表,但沒有好的解釋性,怎么看437.9到底高還是不高,使用

Softmax將得分變成概率

在這里插入圖片描述

Softmax怎么算的
在這里插入圖片描述

就是算個比例吧

現在的w、b就是最好的了嗎
在這里插入圖片描述

(4)損失函數

怎么度量這個結果的好壞標準,使用損失函數

在這里插入圖片描述

交叉熵損失函數

在這里插入圖片描述

可以看到這個損失值是比較大的,那么怎么讓他的損失值變小呢,這里就需要靠梯度下降

(5)梯度下降

在這里插入圖片描述

梯度下降就是為了算出(w、b)

在這里插入圖片描述

(6)非線性分類

線性分類是嘗試使用直線將貓狗分割開,但是如果其分布如下非線性的話
在這里插入圖片描述

就無法將其分割開了

接下來就是使用神經網絡將其分隔開

神經網絡就是在搭積木

有兩個全連接層,除了最上面的和最下面的,搭積木一樣

(7)激活函數

每個格子都有(w*x+b)(激活函數)
在這里插入圖片描述

如下三角形和圓圈,找不到任何直線將其區分開
在這里插入圖片描述

那如果使用一個線性分類器,線性分類的方式將其分隔開,會有漏判
在這里插入圖片描述

沒激活函數的nn 要畫n條直線
在這里插入圖片描述

有激活函數的NN 擬合一條曲線
在這里插入圖片描述
在這里插入圖片描述

激活函數種類如下
在這里插入圖片描述

神經網絡就是一個個的格子,去算一個w、b再算一個激活函數

接下來看其怎么預測的

(8)預測

在這里插入圖片描述

Relu激活函數,若是大于0等于其本身 ,若是小于則等于0

-8套一個激活函數就是0
在這里插入圖片描述

在這里插入圖片描述

(9)訓練

神經網絡的訓練流程就是找到一組合適的w、b使得損失值最小

在這里插入圖片描述

在這里插入圖片描述

三、手寫數字分類

接下來的幾集視頻會帶著大家用pytorch搭建一個神經網絡
實現一個圖像分類的任務

使用的數據為train.csv

資源鏈接:https://download.csdn.net/download/qq_44870829/90487677
在這里插入圖片描述

使用Excel表格打開后如下整個數據集有42000張圖片,每張圖片都是由784個像素點組成的灰度圖,label數據是從0~9。
在這里插入圖片描述

一共784列即784個像素點,每行代表一張灰度圖,一共42000行即42000張圖片

若是使用pytorch搭建神經網絡來做這樣一個圖像分類任務的話,先捋一下邏輯

1,定義網絡結構

#3神經網絡,可以將其看成黑盒子,或者一個 python函數,這個函數有了輸入就有了輸出#784個像素點構成的灰度圖——》函數——》10個概率(0 1 2 3 4 5 6 7 8 9的概率)#那么函數該怎么定義呢,這個步驟就是定義網絡結構的步驟
#定義網絡結構#[1,784]*[784,444] = [1,444]*[444,512] = [1,512]*[512,512] = [1,512]*[512,10] = [1,10]
#輸入層  	in_channel 784   out_channel  444#隱藏層1    in_channel 444   out_channel  512#隱藏層2    in_channel 512   out_channel  512#輸出層    in_channel 512   out_channel  10

(無論中間層是多少,都會有輸出層)

全連接層有兩個最重要的屬性一個叫in_channel 一個叫out_channel,輸入輸出頻道看做成有多少個點,或者 叫多少個特征,或者叫多少個數據

能被數據所確定的只有輸入層的in_channel,輸出層的out_channel,中間層的輸入輸出頻道都是可以 自定義的

接下來就是使用pytorch將上方的網絡搭建起來了,使用torch.nn模塊中的東西

#定義nn神經網絡
import torch
import torch.nn as nn#3神經網絡,可以將其看成黑盒子,或者一個 python函數,這個函數有了輸入就有了輸出
#784個像素點構成的灰度圖——》函數——》10個概率(0 1 2 3 4 5 6 7 8 9的概率)
#那么函數該怎么定義呢,這個步驟就是定義網絡結構的步驟
#定義網絡結構#[1,784]*[784,444] = [1,444]*[444,512] = [1,512]*[512,512] = [1,512]*[512,10] = [1,10]
#輸入層    in_channel 784   out_channel  444
#隱藏層1    in_channel 444   out_channel  512
#隱藏層2    in_channel 512   out_channel  512
#輸出層    in_channel 512   out_channel  10#偽造個隨機數據
data = torch.rand(1, 784) #共784個像素,將其轉為一行784列的數據#序列化(搭積木),里面可以放入任意想要的層,從前向后
model = nn.Sequential(nn.Linear(784, 444),    #Linear全連接層或者稱線性層nn.ReLU(),                                   #加入激活層nn.Linear(444, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),nn.Softmax()                                #將值轉換成概率)#這個函數可以返回一個模型對象給我們
print(model)
# Sequential(
#   (0): Linear(in_features=784, out_features=444, bias=True)
#   (1): ReLU()
#   (2): Linear(in_features=444, out_features=512, bias=True)
#   (3): ReLU()
#   (4): Linear(in_features=512, out_features=512, bias=True)
#   (5): ReLU()
#   (6): Linear(in_features=512, out_features=10, bias=True)
#   (7): Softmax(dim=None)
# )
#現在的model已經是一個模型了 ,但是現在模型里面的w和b是隨機值,是不好用的
#后面還需要通過數據驅動其進行訓練(但是訓練之前還要做一件事情要驗證一下此模型搭建出來合不合理)
#隨機一個數據進行能否得到輸出的十個概率值predict = model(data)   #進行相關的算
print(predict)
# tensor([[0.0944, 0.0975, 0.1039, 0.0938, 0.1050, 0.1013, 0.1024, 0.1010, 0.0998,
#          0.1011]], grad_fn=<SoftmaxBackward0>)

2,整理數據集

接下來就是讀取數據并對其進行一定的整理
訓練是需要數據推動的

import pandas as pdraw_df = pd.read_csv('train.csv')
print(raw_df.head())
#    label  pixel0  pixel1  pixel2  ...  pixel780  pixel781  pixel782  pixel783
# 0      1       0       0       0  ...         0         0         0         0
# 1      0       0       0       0  ...         0         0         0         0
# 2      1       0       0       0  ...         0         0         0         0
# 3      4       0       0       0  ...         0         0         0         0
# 4      0       0       0       0  ...         0         0         0         0
#
# [5 rows x 785 columns]#將標簽那列數據拿出來
label = raw_df['label']
print(label)
# 0        1
# 1        0
# 2        1
# 3        4
# 4        0
#         ..
# 41995    0
# 41996    1
# 41997    7
# 41998    6
# 41999    9
# Name: label, Length: 42000, dtype: int64#將df的數據類型轉成numpy的,去掉索引
label = raw_df['label'].values
print(label)
# [1 0 1 ... 7 6 9]#特征(刪除label列,剩下的就是特征
raw_df = raw_df.drop(['label'], axis=1) #axis=1表示y軸
feature = raw_df.values
print(len(label),len(feature))#將整個數據集劃分成兩個數據集,一個訓練集、一個測試集,80%是用來神經網絡訓練的
#訓練集相當于日常作業,測試集就是考試,日常作業做的好不代表考試做的好,所以還需要測試
#這里的數據集實際上已經被打亂過了,現在直接做個切片即可train_feature = feature[:int(0.8*len(feature))]
train_label = label[:int(0.8*len(label))]
test_feature = feature[int(0.8*len(feature)):]
test_label = label[int(0.8*len(label)):]print(len(train_feature),len(train_label),len(test_feature),len(test_label))
#33600 33600 8400 8400

3,訓練模型

import pandas as pd
#定義nn神經網絡
import torch
import torch.nn as nnraw_df = pd.read_csv('train.csv')
print(raw_df.head())
#    label  pixel0  pixel1  pixel2  ...  pixel780  pixel781  pixel782  pixel783
# 0      1       0       0       0  ...         0         0         0         0
# 1      0       0       0       0  ...         0         0         0         0
# 2      1       0       0       0  ...         0         0         0         0
# 3      4       0       0       0  ...         0         0         0         0
# 4      0       0       0       0  ...         0         0         0         0
#
# [5 rows x 785 columns]#將標簽那列數據拿出來
label = raw_df['label']
print(label)
# 0        1
# 1        0
# 2        1
# 3        4
# 4        0
#         ..
# 41995    0
# 41996    1
# 41997    7
# 41998    6
# 41999    9
# Name: label, Length: 42000, dtype: int64#將df的數據類型轉成numpy的,去掉索引
label = raw_df['label'].values
print(label)
# [1 0 1 ... 7 6 9]#特征(刪除label列,剩下的就是特征
raw_df = raw_df.drop(['label'], axis=1) #axis=1表示y軸
feature = raw_df.values
print(len(label),len(feature))#將整個數據集劃分成兩個數據集,一個訓練集、一個測試集,80%是用來神經網絡訓練的
#訓練集相當于日常作業,測試集就是考試,日常作業做的好不代表考試做的好,所以還需要測試
#這里的數據集實際上已經被打亂過了,現在直接做個切片即可train_feature = feature[:int(0.8*len(feature))]
train_label = label[:int(0.8*len(label))]
test_feature = feature[int(0.8*len(feature)):]
test_label = label[int(0.8*len(label)):]print(len(train_feature),len(train_label),len(test_feature),len(test_label))
#33600 33600 8400 8400#將numpy轉為tensor,還要將其數據類型變為float
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)#3神經網絡,可以將其看成黑盒子,或者一個 python函數,這個函數有了輸入就有了輸出
#784個像素點構成的灰度圖——》函數——》10個概率(0 1 2 3 4 5 6 7 8 9的概率)
#那么函數該怎么定義呢,這個步驟就是定義網絡結構的步驟
#定義網絡結構#[1,784]*[784,444] = [1,444]*[444,512] = [1,512]*[512,512] = [1,512]*[512,10] = [1,10]
#輸入層    in_channel 784   out_channel  444
#隱藏層1    in_channel 444   out_channel  512
#隱藏層2    in_channel 512   out_channel  512
#輸出層    in_channel 512   out_channel  10#偽造個隨機數據
data = torch.rand(1, 784) #共784個像素,將其轉為一行784列的數據#序列化(搭積木),里面可以放入任意想要的層,從前向后
model = nn.Sequential(nn.Linear(784, 444),    #Linear全連接層或者稱線性層nn.ReLU(),                                   #加入激活層nn.Linear(444, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),nn.Softmax()                                #將值轉換成概率)#這個函數可以返回一個模型對象給我們
print(model)
# Sequential(
#   (0): Linear(in_features=784, out_features=444, bias=True)
#   (1): ReLU()
#   (2): Linear(in_features=444, out_features=512, bias=True)
#   (3): ReLU()
#   (4): Linear(in_features=512, out_features=512, bias=True)
#   (5): ReLU()
#   (6): Linear(in_features=512, out_features=10, bias=True)
#   (7): Softmax(dim=None)
# )
#現在的model已經是一個模型了 ,但是現在模型里面的w和b是隨機值,是不好用的
#后面還需要通過數據驅動其進行訓練(但是訓練之前還要做一件事情要驗證一下此模型搭建出來合不合理)
#隨機一個數據進行能否得到輸出的十個概率值# predict = model(data)   #進行相關的算
# print(predict)
# # tensor([[0.0944, 0.0975, 0.1039, 0.0938, 0.1050, 0.1013, 0.1024, 0.1010, 0.0998,
# #          0.1011]], grad_fn=<SoftmaxBackward0>)# 梯度下降(找到一組合適的w和b,讓損失值越小越好),w和b再上面的模型結構中已經定義好了,但是損失值并不知道
# 損失值 使用損失函數,一般都使用交叉熵損失函數
# 瞎子下山
lossfunction = nn.CrossEntropyLoss()
#訓練的時候要使用什么樣的優化器,一般使用Adam
optimizer = torch.optim.Adam(params=model.parameters(), lr=0.001)  #params參數優化,學習率lr(步子)#訓練的輪數
for i in range(100):#清空優化器的梯度(偏導),Adam會存放一些歷史的一些偏導數,所以我們要把它們清空optimizer.zero_grad()#接著走前向傳播的流程(即預測的流程)predict = model(train_feature)#將概率轉換成0~10的索引并打印result = torch.argmax(predict, axis=1)# print(result)                           #tensor([5, 0, 7,  ..., 0, 5, 5])train_acc = torch.mean((result == train_label).to(torch.float))#算預測結果與標準結果之間有多少誤差,即損失值loss = lossfunction(predict, train_label)#有了損失值后要做梯度下降# (在神經網絡中要做梯度下降,要干的事情是先做反向傳播)loss.backward()#梯度下降在optimizer中進行的optimizer.step()    #梯度下降一步#到此整個更新過程就都完事了,每一輪訓練完了,他的損失值和準確率是多少# print(loss.item())      #損失值隨著訓練和迭代是越來越小的,那說明這里面的w和b越來越好#接下來還有個東西就是準確率,準確率怎么搞呢,先分析這個predict出來的是什么print('train loss:{} train acc:{}'.format(loss.item(),train_acc.item()))#清空一下優化器的梯度,再對測試集數據進行預測optimizer.zero_grad()predict = model(test_feature)result = torch.argmax(predict, axis=1)test_acc = torch.mean((result == test_label).to(torch.float))loss = lossfunction(predict, test_label)#測試的時候是不需要更新的,loss.backward() optimizer.step() 就不用寫了print('test loss:{} test acc:{}'.format(loss.item(), test_acc.item()))

4,勘誤

當我們用神經網絡做分類的時候
如對手寫數字圖片進行分類,那在做分類的時候呢,一般是在最后加入softmax的運算

但由于pytorch它的交叉熵損失loss_fn = nn.CrossEntropyLoss()

它里面會默認把算出來的結果進行一次softmax的運算,所以一般來說nn的softmax是多余的,可以刪除掉
在這里插入圖片描述

若是不將其刪掉,上面做了一次softmax, nn.CrossEntropyLoss()又會計算了一次損失

loss_fn = nn.CrossEntropyLoss()

當然如果你的網絡數據和網絡結構都比較簡單,那么做兩次softmax也能收斂
但當這個數據比較復雜,任務復雜,網絡也比較復雜的時候呢,做兩次softmax,那么他的一個收斂的可能性就會大大降低

所以當你的損失函數是CrossEntropyLoss時,最后是不需要加入softmax的

5,保存模型

如果沒保存模型的話一退出就沒了,所以保存模型加個torch.save()

torch.save(model.state_dict(), 'model.pt') #model.state_dict()就是模型中的w和b

6,加載模型并預測

我們保存模型的真正目的其實是為了我們在預測的時候可以加載我們之前已經訓練好的模型,直接拿過來用

而不是我在預測之前還要重新訓練一下模型

#加載模型文件里的參數w、b
import torch
import torch.nn as nnimport pandas as pdraw_df = pd.read_csv('train.csv')
print(raw_df.head())
#    label  pixel0  pixel1  pixel2  ...  pixel780  pixel781  pixel782  pixel783
# 0      1       0       0       0  ...         0         0         0         0
# 1      0       0       0       0  ...         0         0         0         0
# 2      1       0       0       0  ...         0         0         0         0
# 3      4       0       0       0  ...         0         0         0         0
# 4      0       0       0       0  ...         0         0         0         0
#
# [5 rows x 785 columns]#將標簽那列數據拿出來
label = raw_df['label']
print(label)
# 0        1
# 1        0
# 2        1
# 3        4
# 4        0
#         ..
# 41995    0
# 41996    1
# 41997    7
# 41998    6
# 41999    9
# Name: label, Length: 42000, dtype: int64#將df的數據類型轉成numpy的,去掉索引
label = raw_df['label'].values
print(label)
# [1 0 1 ... 7 6 9]#特征(刪除label列,剩下的就是特征
raw_df = raw_df.drop(['label'], axis=1) #axis=1表示y軸
feature = raw_df.values
print(len(label),len(feature))#將整個數據集劃分成兩個數據集,一個訓練集、一個測試集,80%是用來神經網絡訓練的
#訓練集相當于日常作業,測試集就是考試,日常作業做的好不代表考試做的好,所以還需要測試
#這里的數據集實際上已經被打亂過了,現在直接做個切片即可train_feature = feature[:int(0.8*len(feature))]
train_label = label[:int(0.8*len(label))]
test_feature = feature[int(0.8*len(feature)):]
test_label = label[int(0.8*len(label)):]#將numpy轉為tensor,還要將其數據類型變為float
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)#把參數塞進模型里面
#首先要有一個模型對象,模型結構
#序列化(搭積木),里面可以放入任意想要的層,從前向后
model = nn.Sequential(nn.Linear(784, 444),    #Linear全連接層或者稱線性層nn.ReLU(),                                   #加入激活層nn.Linear(444, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),nn.Softmax()                                #將值轉換成概率)#加載模型文件參數
params = torch.load("model.pt")
model.load_state_dict(params) #把模型中的參數全部塞到model中去了#加載完模型后就是預測了
new_test_data = test_feature[100:111]
new_test_label = test_label[100:111]predict = model(new_test_data)
result = torch.argmax(predict,axis=1)
print(new_test_label)
print(result)
#對比兩者結果是差不多的,可以看到如下所示,有個別預測不對
# tensor([5, 1, 8, 3, 6, 2, 7, 9, 6, 3, 6])
# tensor([5, 1, 8, 8, 6, 2, 4, 4, 6, 5, 6])

7,使用GPU加速

Pytorch的

能夠定義模型結構,能夠加載模型,能夠使用模型進行預測
但是這里面還有一個功能是欠缺的,就是使用GPU進行加速

這個時候有人問了,不是裝好了GPU版本的pytorch嗎
如果沒有在代碼中真正調用GPU加速的命令,它是不會把數據放到顯存里面去存儲,并且使用GPU進行計算的
在這里插入圖片描述

在這里插入圖片描述

import pandas as pd
#定義nn神經網絡
import torch
import torch.nn as nnraw_df = pd.read_csv('train.csv')
print(raw_df.head())
#    label  pixel0  pixel1  pixel2  ...  pixel780  pixel781  pixel782  pixel783
# 0      1       0       0       0  ...         0         0         0         0
# 1      0       0       0       0  ...         0         0         0         0
# 2      1       0       0       0  ...         0         0         0         0
# 3      4       0       0       0  ...         0         0         0         0
# 4      0       0       0       0  ...         0         0         0         0
#
# [5 rows x 785 columns]#將標簽那列數據拿出來
label = raw_df['label']
print(label)
# 0        1
# 1        0
# 2        1
# 3        4
# 4        0
#         ..
# 41995    0
# 41996    1
# 41997    7
# 41998    6
# 41999    9
# Name: label, Length: 42000, dtype: int64#將df的數據類型轉成numpy的,去掉索引
label = raw_df['label'].values
print(label)
# [1 0 1 ... 7 6 9]#特征(刪除label列,剩下的就是特征
raw_df = raw_df.drop(['label'], axis=1) #axis=1表示y軸
feature = raw_df.values
print(len(label),len(feature))#將整個數據集劃分成兩個數據集,一個訓練集、一個測試集,80%是用來神經網絡訓練的
#訓練集相當于日常作業,測試集就是考試,日常作業做的好不代表考試做的好,所以還需要測試
#這里的數據集實際上已經被打亂過了,現在直接做個切片即可train_feature = feature[:int(0.8*len(feature))]
train_label = label[:int(0.8*len(label))]
test_feature = feature[int(0.8*len(feature)):]
test_label = label[int(0.8*len(label)):]print(len(train_feature),len(train_label),len(test_feature),len(test_label))
#33600 33600 8400 8400#
#將numpy轉為tensor,還要將其數據類型變為float
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)#將數據存放到顯存中
train_feature = train_feature.cuda()
train_label = train_label.cuda()
test_feature = test_feature.cuda()
test_label = test_label.cuda()#3神經網絡,可以將其看成黑盒子,或者一個 python函數,這個函數有了輸入就有了輸出
#784個像素點構成的灰度圖——》函數——》10個概率(0 1 2 3 4 5 6 7 8 9的概率)
#那么函數該怎么定義呢,這個步驟就是定義網絡結構的步驟
#定義網絡結構#[1,784]*[784,444] = [1,444]*[444,512] = [1,512]*[512,512] = [1,512]*[512,10] = [1,10]
#輸入層    in_channel 784   out_channel  444
#隱藏層1    in_channel 444   out_channel  512
#隱藏層2    in_channel 512   out_channel  512
#輸出層    in_channel 512   out_channel  10#偽造個隨機數據
data = torch.rand(1, 784) #共784個像素,將其轉為一行784列的數據#序列化(搭積木),里面可以放入任意想要的層,從前向后
model = nn.Sequential(nn.Linear(784, 444),    #Linear全連接層或者稱線性層nn.ReLU(),                                   #加入激活層nn.Linear(444, 512),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),#nn.Softmax()                                #將值轉換成概率)model = model.cuda()    #將model的數據從內存轉到顯存中#這個函數可以返回一個模型對象給我們
print(model)
# Sequential(
#   (0): Linear(in_features=784, out_features=444, bias=True)
#   (1): ReLU()
#   (2): Linear(in_features=444, out_features=512, bias=True)
#   (3): ReLU()
#   (4): Linear(in_features=512, out_features=512, bias=True)
#   (5): ReLU()
#   (6): Linear(in_features=512, out_features=10, bias=True)
#   (7): Softmax(dim=None)
# )
#現在的model已經是一個模型了 ,但是現在模型里面的w和b是隨機值,是不好用的
#后面還需要通過數據驅動其進行訓練(但是訓練之前還要做一件事情要驗證一下此模型搭建出來合不合理)
#隨機一個數據進行能否得到輸出的十個概率值# predict = model(data)   #進行相關的算
# print(predict)
# # tensor([[0.0944, 0.0975, 0.1039, 0.0938, 0.1050, 0.1013, 0.1024, 0.1010, 0.0998,
# #          0.1011]], grad_fn=<SoftmaxBackward0>)# 梯度下降(找到一組合適的w和b,讓損失值越小越好),w和b再上面的模型結構中已經定義好了,但是損失值并不知道
# 損失值 使用損失函數,一般都使用交叉熵損失函數
# 瞎子下山
lossfunction = nn.CrossEntropyLoss()
#訓練的時候要使用什么樣的優化器,一般使用Adam
optimizer = torch.optim.Adam(params=model.parameters(), lr=0.001)  #params參數優化,學習率lr(步子)#訓練的輪數
for i in range(100):#清空優化器的梯度(偏導),Adam會存放一些歷史的一些偏導數,所以我們要把它們清空optimizer.zero_grad()#接著走前向傳播的流程(即預測的流程)predict = model(train_feature)#將概率轉換成0~10的索引并打印result = torch.argmax(predict, axis=1)# print(result)                           #tensor([5, 0, 7,  ..., 0, 5, 5])train_acc = torch.mean((result == train_label).to(torch.float))#算預測結果與標準結果之間有多少誤差,即損失值loss = lossfunction(predict, train_label)#有了損失值后要做梯度下降# (在神經網絡中要做梯度下降,要干的事情是先做反向傳播)loss.backward()#梯度下降在optimizer中進行的optimizer.step()    #梯度下降一步#到此整個更新過程就都完事了,每一輪訓練完了,他的損失值和準確率是多少# print(loss.item())      #損失值隨著訓練和迭代是越來越小的,那說明這里面的w和b越來越好#接下來還有個東西就是準確率,準確率怎么搞呢,先分析這個predict出來的是什么print('train loss:{} train acc:{}'.format(loss.item(),train_acc.item()))#清空一下優化器的梯度,再對測試集數據進行預測optimizer.zero_grad()predict = model(test_feature)result = torch.argmax(predict, axis=1)test_acc = torch.mean((result == test_label).to(torch.float))loss = lossfunction(predict, test_label)#測試的時候是不需要更新的,loss.backward() optimizer.step() 就不用寫了print('test loss:{} test acc:{}'.format(loss.item(), test_acc.item()))torch.save(model.state_dict(), 'model.pt') #model.state_dict()就是模型中的w和b

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72498.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72498.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72498.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【開源免費】基于SpringBoot+Vue.JS電商應用系統(JAVA畢業設計)

本文項目編號 T 242 &#xff0c;文末自助獲取源碼 \color{red}{T242&#xff0c;文末自助獲取源碼} T242&#xff0c;文末自助獲取源碼 目錄 一、系統介紹二、數據庫設計三、配套教程3.1 啟動教程3.2 講解視頻3.3 二次開發教程 四、功能截圖五、文案資料5.1 選題背景5.2 國內…

經歷過的IDEA+Maven+JDK一些困惑

注意事項&#xff1a;由于使用過程中是IDEA綁定好另外2個工具&#xff0c;所以報錯統一都顯示在控制臺&#xff0c;但要思考和分辨到底是IDEA本身問題導致的報錯&#xff0c;還是maven導致的 使用前的配置 編輯期 定義&#xff1a;指的是從open projects開始&#xff0c;到執行…

【推理】大模型ReasonGraph:推理路徑的可視化論文及代碼分析

ReasonGraph:推理路徑的可視化 ReasonGraph demo http://192.168.50.197:5001/ 作者的其他論文 ** ** LLM推理方法的相關工作

學習路之TP6 --重寫vendor目錄下的文件(服務覆蓋command---優點:命令前后一致)

學習路之TP6 --重寫vendor目錄下的文件 一、新建命令文件&#xff1a;二、復制修改&#xff1a;Server.php三、新建服務類&#xff1a;WorkmanService.php四、注冊服務五、運行效果 有需求要重寫vendor\topthink\think-worker\src\command\Server.php 以實現修改代碼 一、新建命…

【藍圖使用】繪制mesh頂點的法線

文章目錄 繪制法線Normal準備工作UE5資源制作藍圖制作 參考 繪制法線Normal 參考[1]打算用藍圖走一遍渲染管線&#xff0c;還是可以的 準備工作 Blender制作一個三個頂點的模型 要不要材質無所謂&#xff0c;就一個三個頂點的mesh即可&#xff0c;參考[2] 找到一個法線貼…

【算法學習之路】10.二叉樹

二叉樹 前言一.簡介二.題目123 前言 我會將一些常用的算法以及對應的題單給寫完&#xff0c;形成一套完整的算法體系&#xff0c;以及大量的各個難度的題目&#xff0c;目前算法也寫了幾篇&#xff0c;題單正在更新&#xff0c;其他的也會陸陸續續的更新&#xff0c;希望大家點…

AI軟件棧:推理框架(二)-Llama CPP1

Llama CPP的主要構造&#xff0c;GGUF和GGML為兩個主要部分&#xff0c;包括模型描述文件和模型參數存儲文件 文章目錄 GGUF構建圖讀取權重 GGUF llama.cpp 的作者 Georgi Gerganov 提出的新一代大模型描述文件 GPT-Generated Unified Format&#xff0c;繼承自GGML&#xff0…

CentOS 7 64 安裝 Docker

前言 在虛擬機中安裝 Docker 是一種常見的測試和開發環境搭建方式。通過在虛擬機上安裝 Docker&#xff0c;可以方便地創建和管理容器化應用&#xff0c;同時避免對宿主機系統造成影響。以下是在 CentOS 7 虛擬機中安裝 Docker 的詳細步驟。 1. 更新系統&#xff08;可以不操作…

Flutter_學習記錄_video_player、chewie 播放視頻

1. video_player 視頻播放 插件地址&#xff1a;https://pub.dev/packages/video_player 添加插件 導入頭文件 import package:video_player/video_player.dart;Android配置&#xff08;iOS不用配置&#xff09; 修改這個文件&#xff1a;/android/app/src/main/AndroidMani…

VSCode通過SSH免密遠程登錄Windows服務器

系列 1.1 VSCode通過SSH遠程登錄Windows服務器 1.2 VSCode通過SSH免密遠程登錄Windows服務器 文章目錄 系列1 準備工作2 本地電腦配置2.1 生成密鑰2.2 VS Code配置密鑰 3. 服務端配置3.1 配置SSH服務器sshd_config3.2 復制公鑰3.3 配置權限&#xff08;常見問題&#xff09;3.…

強大的數據庫DevOps工具:NineData 社區版

本文作者司馬遼太杰&#xff0c; gzh&#xff1a;程序猿讀歷史 在業務快速變化與數據安全日益重要的今天&#xff0c;生產數據庫變更管理、版本控制、數據使用是數據庫領域的核心挑戰之一。傳統的解決方式往往采用郵件或即時通訊工具發起審批流程&#xff0c;再通過堡壘機直連數…

離線服務器ollama新增qwen2:0.5b模型

離線服務器ollama新增qwen2:0.5b模型 Dify集成ollama前面已經介紹過離線服務器CentOS使用的docker安裝的ollama&#xff0c;其中在ollama中已經安裝了deepseek-r1:1.5b。目前的需求是需要再安裝一個qwen2:0.5b的模型&#xff0c;那么如何安裝呢&#xff1f; 1.首先在有網的服…

淺談StarRocks數據庫簡介及應用

StarRocks是一款高性能的實時分析型數據庫&#xff0c;專為復雜的SQL查詢提供極高的性能&#xff0c;尤其適用于數據分析場景。它是一款開源的新一代極速全場景MPP&#xff08;Massively Parallel Processing&#xff0c;大規模并行處理&#xff09;數據庫&#xff0c;致力于構…

Cadence學習筆記4

想到一個思路理解過程&#xff0c;記錄一下&#xff1a; 就是我在別的地方&#xff0c;前一天的那些 Lib 都不在了&#xff0c;突然發現自己好像就在 Cadence 中畫不了 PCB 了。這就引發了我思考在 Cadence 中如何進行繪制的一個整體的流程。 首先得有原理圖&#xff0c;那么原…

Linux--git

ok&#xff0c;我們今天來學習如何在Linux上建立鏈接git 版本控制器Git 不知道你?作或學習時&#xff0c;有沒有遇到這樣的情況&#xff1a;我們在編寫各種?檔時&#xff0c;為了防??檔丟失&#xff0c;更改 失誤&#xff0c;失誤后能恢復到原來的版本&#xff0c;不得不…

(七)Spring Boot學習——Redis使用

有部分內容是常用的&#xff0c;為了避免每次都查詢數據庫&#xff0c;將部分數據存入Redis。 一、 下載并安裝 Redis Windows 版的 Redis 官方已不再維護&#xff0c;你可以使用 微軟提供的 Redis for Windows 版本 或者 使用 WSL&#xff08;Windows Subsystem for Linux&a…

HarmonyOS NEXT 聲明式UI語法學習筆記-創建自定義組件

基礎語法概述 ArkTS的基本組成 裝飾器&#xff1a;用于裝飾類、結構、方法以及變量&#xff0c;并賦予其特殊含義。如上圖都是裝飾器&#xff0c;Component表示自定義組件&#xff0c;Entry表示表示自定義組件的入口組件&#xff0c;State表示組件中的狀態變量&#xff0c;當狀…

【ElasticSearch】學習筆記

一、lucene的組成 segment是一個具備完整搜索功能的最小單元。 多個segment組成了一個單機文本檢索庫lucene。 inverted index:倒排索引&#xff0c;用于快速根據關鍵詞找到對應的文章term index: 構建出關鍵詞的目錄樹&#xff0c;解決了term dictionary數據量過大&#xff…

SSL/TLS 1.2過程:Client端如何驗證服務端證書?

快速回顧非對稱加密和對稱加密 首先快速說一下非對稱加密和對稱加密。非對稱加密&#xff0c;就是有一個公鑰和私鑰(成對存在)。 公鑰對一段文本A加密得到文本B&#xff0c;只有對應的私鑰能對B解密得到A。 私鑰對一段文本C加密得到文本D&#xff0c;只有對應的公鑰能對D解密得…

ChatGPT、DeepSeek、Grok:AI 語言模型的差異與應用場景分析

&#x1f4dd;個人主頁&#x1f339;&#xff1a;一ge科研小菜雞-CSDN博客 &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; 1. 引言 人工智能&#xff08;AI&#xff09;語言模型正在快速發展&#xff0c;ChatGPT&#xff08;OpenAI&#xff09;、DeepSe…