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