零基礎學習人工智慧—Python—Pytorch學習(五)

kiba518發表於2024-08-18

前言

上文有一些文字打錯了,已經進行了修正。
本文主要介紹訓練模型和使用模型預測資料,本文使用了一些numpy與tensor的轉換,忘記的可以第二課的基礎一起看。

線性迴歸模型訓練

結合numpy使用

首先使用datasets做一個資料X和y,然後結合之前的內容,求出y_predicted。

# pip install matplotlib
# pip install scikit-learn
import torch
import numpy as np
import torch.nn as nn
from sklearn import datasets
import matplotlib.pyplot as plt
# 0)準備資料
# 生成100行1列的資料X_numpy和Y_numpy
# noise=20: 值越大,資料越具有隨機性。
# random_state=1: 設定隨機種子,以確保每次生成的X_numpy和Y_numpy相同
X_numpy, Y_numpy = datasets.make_regression( n_samples=100, n_features=1, noise=20, random_state=1) 

X = torch.from_numpy(X_numpy.astype(np.float32))
y = torch.from_numpy(Y_numpy.astype(np.float32))
y = y.view(y.shape[0], 1) #  100 行 1 列 y.shape是100行1列,所以y.shape[0]=100,y.shape[1]=1
n_samples, n_features = X.shape
# 1)模型
input_size = n_features
output_size = 1
model = nn.Linear(input_size, output_size)
# 2)損失函式和最佳化器
learning_rate = 0.01
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
n_iter = 100
#下面迴圈的呼叫了model裡的前向傳播和反覆的使用損失函式進行反向傳播來更新w和b,就是訓練模型
for epoch in range(n_iter):
    # forward pass and loss
    y_predicted = model(X)
    loss = criterion(y_predicted, y)
    # backward pass
    loss.backward()
    # update
    optimizer.step()
    optimizer.zero_grad()
    if (epoch+1) % 10 == 0:
        print(f'epoch:{epoch+1},loss ={loss.item():.4f}')
# plot
# model(X).detach()是從model裡分離出一個張量,這個張量跟model沒有關係了,簡單理解為生成了新張量物件,記憶體地址和model不一樣了。
div_tensor = model(X).detach()
predicted = div_tensor.numpy() # 返回numpy.ndarray型別的張量,相當於轉了型別
# plt.plot是在座標系上繪製影像 
# 引數1是x座標軸的值,引數2是y座標軸的值,引數3=是fmt (格式字串)
# 引數3介紹:ro是紅色圓點r=red o=circle  bo是藍色圓點 b是藍色 g是綠色
plt.plot(X_numpy,Y_numpy,'ro')
plt.plot(X_numpy, predicted, 'bo')
plt.show()

這裡我們已經提到了訓練的模型的概念了。
我們在for迴圈的呼叫了model裡的前向傳播,然後再反覆的使用損失函式進行反向傳播來更新w和b,這操作就是訓練模型。
訓練結束後,我們就可以使用model,接受新矩陣,來預測y。
這裡,我們是在迴圈結束後,又使用我們訓練的模型,重新對x進行了一次預測。
執行如下圖:
image

可以看到預測的y都在一條線上,這是因為預測值是基於w和b計算而得,所以,值總是在直線上。
注:所謂x和y的線性關係就是x和y的元素之間的很複雜的倍數關係。
關於線性迴歸,可以參考下圖,稍微瞭解一下就行。

image

完整的訓練例子

下面是一個完整的訓練模型,然後使用模型預測的例子。
首先使用datasets.load_breast_cancer()獲取資料。資料X可以理解為一個患者的指標資料,Y可以理解為這個患者是否是癌症患者(資料都是0和1)。
然後透過訓練模型,我們給一組患者的X指標資料,就可以預測患者是否是癌症患者了。

# pip install matplotlib
# pip install scikit-learn
import torch
import numpy as np
import torch.nn as nn
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

# 0)prepare data
bc = datasets.load_breast_cancer() #載入乳腺癌資料集
print(bc.keys()) #data(特徵資料)、target(標籤)、feature_names(特徵名)
X, y = bc.data, bc.target  #取特徵資料作為輸入資料x(通常是一個二維陣列或 DataFrame),取標籤作為目標資料y(通常是一維陣列或 Series)
print("x 569*30",X.shape,"y 569*1",y.shape)
n_samples, n_features = X.shape # n_samples=569 n_features=30
#train_test_split用於隨機地將資料集拆分成訓練集和測試
# X_train: 拆分後的訓練集的特徵部分,包含用於訓練模型的大部分資料。
# X_test: 拆分後的測試集的特徵部分,包含用於評估模型的小部分資料。
# y_train: 對應 X_train 的目標值,用於訓練模型。
# y_test: 對應 X_test 的目標值,用於評估模型。
# test_size=0.2表示將 20% 的資料用於測試,剩下的 80% 用於訓練
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=1234)

print("X_train 455*30",X_train.shape,"X_test 114*1",X_test.shape,"y_train 455*1",y_train.shape,"y_test 114*1",y_test.shape)
print("型別1:X_train", type(X_train),"X_test", type(X_test),"y_train", type(y_train),"y_test", type(y_test))
# scale
# StandardScaler 用於對資料進行標準化(即縮放),縮放的方法是使用[標準化公式],
# 大概計算邏輯就是每個x調整為 (x-x集合的平均值)/根號((x-x集合的平均值)²  )
# 經過標準化後,每個特徵(特徵=列)的均值會變為 0,標準差(平方差)變為 1。 
sc = StandardScaler()

# fit_transform函式里會計算均值和標準差,然後下面的transform會使用fit_transform裡的均值和方差
X_train = sc.fit_transform(X_train) #使用計算的均值和方差來標準化X_train
X_test = sc.transform(X_test) #使用fit_transform計算的均值和方差來標準化X_test

#x,y相關資料轉tensor陣列
X_train = torch.from_numpy(X_train.astype(np.float32))
X_test = torch.from_numpy(X_test.astype(np.float32))
y_train = torch.from_numpy(y_train.astype(np.float32))
y_test = torch.from_numpy(y_test.astype(np.float32))

print("型別2:X_train", type(X_train),"X_test", type(X_test),"y_train", type(y_train),"y_test", type(y_test))

print("X_train 455*30",X_train.shape,"X_test 114*1",X_test.shape,"y_train 455*1",y_train.shape,"y_test 114*1",y_test.shape)

# 轉成tensor的y格式不對,進行view調整,原始size為torch.Size([114]) 調整後為:torch.Size([114, 1])
y_train = y_train.view(y_train.shape[0],1)
y_test = y_test.view(y_test.shape[0], 1)
 
# 1)model
# f=wx + b,sigmoid at the end


class LogisticRegression(nn.Module):
    def __init__(self, n_input_features):
        super(LogisticRegression, self).__init__()
        self.linear = nn.Linear(n_input_features, 1) # 引數1:30(x的列)引數2:1(預測y的列)

    def forward(self, x):
        y_predicted = torch.sigmoid(self.linear(x)) #self.linear(x)執行的前向傳播,sigmoid它將返回值轉換為 [0, 1] 之間的機率值(機率值就是百分比,例如返回0.7,就是70%的意思)
        return y_predicted


model = LogisticRegression(n_features)
# 2)loss and optimizer
learning_rate = 0.01
criterion = nn.BCELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# 3)training loop
num_epochs = 100
for epoch in range(num_epochs):
    # forward pass and loss
    y_predicted = model(X_train)
    loss = criterion(y_predicted,y_train)
    # backward pass
    loss.backward()
    # updates
    optimizer.step()
    # zero gradients
    optimizer.zero_grad()
    if(epoch+1)% 10 == 0:print(f'epoch:{epoch+1},loss ={loss.item():.4f}')
# 模型的使用,這裡是以前沒有的
with torch.no_grad():
    y_predicted = model(X_test) #把X_test傳到模型裡,得到X_test的預期y
    y_predicted_cls=y_predicted.round() #四捨五入 y_predicted = torch.tensor([0.3, 0.7, 0.5, 0.2, 0.9])  y_predicted.round()的結果為: tensor([0., 1., 0., 0., 1.])
    #eq(y_test): 這個方法比較 y_predicted_cls 和 y_test 之間的每個元素,如果兩個值相等則返回 True,否則返回 False。返回的結果是一個布林張量。
    eq = y_predicted_cls.eq(y_test)
    print("equal",eq)
    eqsum = eq.sum()
    print("eqsum",eqsum)
    print("y_test.shape[0]", y_test.shape[0]) # y_test.shape[0]是 返回y_test的行,他原來是114行1列的矩陣,所以返回114
    float_y_test= float(y_test.shape[0]) #轉為float為下面除法準備
    print("float(y_test.shape[0])", float_y_test)
    acc=eqsum/float_y_test
    print(f'X_test預測的y與y_test的相似度 accuracy ={acc:.4f}')

這樣,我們不僅訓練了模型,還使用模型預測了一組沒有訓練過的資料,併成功的預測出了,Y的值(患者是否是癌症),然後拿我們的預測資料,跟真實資料比較一下,正確率是91.23%
image
傳送門:
零基礎學習人工智慧—Python—Pytorch學習(一)
零基礎學習人工智慧—Python—Pytorch學習(二)
零基礎學習人工智慧—Python—Pytorch學習(三)
零基礎學習人工智慧—Python—Pytorch學習(四)
零基礎學習人工智慧—Python—Pytorch學習(五)


注:此文章為原創,任何形式的轉載都請聯絡作者獲得授權並註明出處!



若您覺得這篇文章還不錯,請點選下方的【推薦】,非常感謝!

https://www.cnblogs.com/kiba/p/18356904

相關文章