李沐動手深度學習(pycharm中運行筆記)——09.softmax回歸+圖像分類數據集+從零實現+簡潔實現

09.softmax回歸+圖像分類數據集+從零實現+簡潔實現(與課程對應)

目錄

?一、softmax回歸

?1、回歸 vs 分類

2、經典分類數據集:?

3、從回歸到分類——均方損失

4、從回歸到多類分類——無校驗比例

?5、從回歸到多類分類——校驗比例

?6、softmax和交叉熵損失

7、總結

二、損失函數

1、均方損失函數 L2?loss

2、絕對值損失函數L1 loss

3、Huber‘s 魯棒損失

三、圖片分類數據集

四、從零實現

五、簡潔實現?


?一、softmax回歸

?1、回歸 vs 分類

回歸估計一個連續值:例如房子賣的價格

  • 單連續數值輸出
  • 自然區間R
  • 跟真實值的區別作為損失

分類預測一個離散類別:例如一個圖片里面是貓還是狗

  • 通常多個輸出
  • 輸出?i 是預測為第 i 類的置信度。

2、經典分類數據集:?

MNIST 數據集?:一個非常經典的數據集,用于識別手寫數字 0 到 9,是一個十類分類問題。

?

ImageNet 數據集?:深度學習中特別經典的數據集,有 100 萬張圖片,每一張圖片是一個自然物體,屬于 1000 類自然物體之一,其中包含大概 100 種不同的狗 ,該問題為 1000 類的分類問題。

3、從回歸到分類——均方損失

  • 類別編碼?:
    • 編碼原因?:類別常為字符串,不是數值,需進行編碼處理。
    • 編碼方式?:若有 n 個類別,采用一位有效編碼。標號是長為 n 的向量 Y1、Y2 … YN ,若真實類別是第 i 個,則 Yi 等于 1,其他元素全部為 0 。

  • 模型訓練與預測?:
    • 訓練方法?:編碼后可用回歸問題的均方損失進行訓練,無需改動。
    • 預測方式?:訓練出模型后,做預測時選取使置信度值最大化的 i,即通過 argmax o i 得到預測標號 yhat 。

4、從回歸到多類分類——無校驗比例

  • Softmax 回歸的問題及目標
    • 關注置信度?:在分類中,更關心對正確類別的置信度要足夠大,而非實際值。
    • 目標函數改進?:希望正確類別 y 的置信度 oy 遠大于其他非正確類的 oi,數學表示為 oy - oi 大于某閾值 Delta,以此拉開正確類與其他類的距離(最大值作為預測、需要更置信的識別正確類)。

?5、從回歸到多類分類——校驗比例

  • 輸出處理的想法
    • 輸出值區間調整?:將輸出值放到合適區間能讓后續處理更簡單,比如希望輸出是概率。
    • 引入 Softmax 操作?:對輸出向量 o 應用 Softmax 操作得到 y hat 向量,其元素非負且和為 1,滿足概率屬性。
    • Softmax 具體計算?:y hat 的第 i 個元素等于 o 的第 i 個元素做指數后,除以所有 o 元素做指數的和,這樣 y hat 就可作為概率。

?6、softmax和交叉熵損失

  • 交叉熵基本概念
    • 衡量概率區別:使用交叉熵(cross entropy)衡量兩個概率的區別,將其作為損失來比較預測概率和真實概率。
    • 離散概率公式:假設有兩個離散概率 p 和 q,有 n 個元素,交叉熵公式為對每個元素 i,負的 pi 乘以 log qi 然后求和。

  • 在分類問題中的損失計算
    • 損失公式:對于真實標號 y 和預測標號 y hat,損失 l (y, y hat) 等于對所有 i 類別求和,負的 yi 乘以 log yi hat 。
    • 簡化計算:由于 y 中只有一個元素為 1 其余為 0,求和可簡化為負的對真實類別 y 的預測值 y hat 求 log 。

  • 與梯度的關系
    • 梯度計算:損失的梯度是真實概率和預測概率的區別,如損失對 DOI 求導等于 Softmax 的第二個元素減去真實類別 y。
    • 梯度下降作用:梯度下降時不斷減去真實和預測概率的區別,使預測的 Softmax 值和真實的 y 更相近 。

7、總結

  • Softmax回歸是一個多類分類模型
  • 使用Softmax操作子得到每個類的預測置信度
  • 使用交叉熵來衡量預測和標號的區別

二、損失函數

損失函數用于衡量預測值和真實值間的區別,在機器學習里是重要概念。簡單介紹三個常用的損失函數。

1、均方損失函數 L2?loss

  • 定義?:均方損失又叫 L2?loss,定義為真實值 y 減去預測值 y',做平方再除以 2,這樣求導數時 2 和 1/2 抵消變為 1。
  • 特性可視化?:用三條曲線可視化其特性,藍色曲線表示 y = 0 時變換預測值 y' 的函數,是二次函數且為偶函數;橙色線表示損失函數的梯度,是穿過原點的一次函數。
  • 參數更新?:梯度決定參數更新方式,預測值 y' 與真實值 y 距離遠時梯度大,參數更新多;靠近時梯度絕對值變小,參數更新幅度變小。

?

2、絕對值損失函數L1 loss

  • L1 損失函數定義
    • 公式形式:L1 損失函數定義為預測值減去真實值的絕對值,反過來也一樣,即 | 預測值 - 真實值 |。
  • 函數曲線情況
    • 曲線呈現:藍色線是損失函數曲線,當 y = 0 時的樣子;綠色線是似然函數曲線,在原點處有一個很尖的點。
  • L1 損失函數導數
    • 大于 0 時導數:當 y' 大于 0 時,導數為常數 1。
    • 小于 0 時導數:當 y' 小于 0 時,導數為常數 -1。
    • 特殊點情況:由于絕對值函數在 0 點處不可導,其 subgradients(次梯度)可以在 -1 和 1 之間 。
  • L1 損失函數特性
    • 距離遠時特點:當預測值跟真實值隔得比較遠時,不管距離多遠,梯度永遠是常數,這帶來穩定性好處,權重更新不會特別大。
    • 距離近時劣勢:在零點處不可導,且在零點處有從 -1 到 1 之間的劇烈變化,這種不平滑性導致在預測值和真實值靠得比較近,即優化末期時可能變得不穩定 。

3、Huber‘s 魯棒損失

  • Harbor 魯棒損失函數定義
    • 差值較大情況:當預測值和真實值差的絕對值大于 1 時,損失函數是絕對值誤差(y 減去 y 一撇的絕對值)并減去 LNG,使曲線能連起來。
    • 差值較近情況:當預測值和真實值差的絕對值小于等于 1 時,損失函數是平方誤差。
  • Harbor 魯棒損失函數曲線特點
    • 藍色曲線:在正 1 負 1 之間是平滑二次函數曲線,之外是另一條曲線。
    • 綠色線(Sech 函數):類似高斯分布,在原點處不像絕對值誤差那樣尖銳。
  • Harbor 魯棒損失函數導數特點
    • 差值較大時:當 y 撇大于 1 或者小于 -1 時,導數是常數。
    • 差值較小時:當 y 撇在 -1 到 1 之間時,導數是漸變過程。
    • 導數好處:預測值和真實值差得遠時,梯度用均勻力度往回拉;靠近時,梯度絕對值變小,保證優化平滑,避免數值問題。

三、圖片分類數據集

MNIST數據集是圖像分類中廣泛使用的數據集之一,但作為基準數據集過于簡單,使用類似但更復雜的Fashion-MNIST數據集。

1、導入庫

import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l

2、?通過框架中的內置函數,將Fashion-MNIST數據集下載并讀取到內存中

# 通過ToTensor實例將圖像數據從PIL類型變換成32位浮點數格式;并除以255使得所有像素的數值均在0到1之間
trans = transforms.ToTensor()  # 預處理,用于將圖片轉為tensor
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)  # 在torchvision.datasets找到FashionMNIST數據集,參數:root="../data"下載目錄, train=True下載訓練數據集, transform=trans圖片轉為pytorch的tensor, download=True下載
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)
print("len(mnist_train):", len(mnist_train), "\nlen(mnist_test):", len(mnist_test))
print("mnist_train[0][0].shape,訓練集中第一張圖片的形狀:", mnist_train[0][0].shape, "\nmnist_train[0][1],訓練集中第一張圖片的標簽:", mnist_train[0][1])  # mnist_train[0][0]是圖片、mnist_train[0][1]是標簽

3、?兩個可視化數據集的函數,來畫一下數據集

def get_fashion_mnist_labels(labels):"""返回Fashion-MNIST數據集的文本標簽"""text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):"""繪制圖像列表"""figsize = (num_cols * scale, num_rows * scale)_, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)  # 使用subplots創建子圖axes = axes.flatten()for i, (ax, img) in enumerate(zip(axes, imgs)):if torch.is_tensor(img):ax.imshow(img.numpy())  # 圖片張量else:ax.imshow(img)  # PIL圖片ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axesX, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))  # 加載批量圖片
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y))  # 顯示圖片并添加標簽
d2l.plt.show()  # 圖片在線展示

4、?讀取一小批量數據,大小batch_size

batch_size = 256
def get_dataloader_workers():"""使用4個進程來讀取的數據"""return 0  # 寫幾就是幾個進程train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers())
timer = d2l.Timer()
for X, y in train_iter:continue
print(f'{timer.stop():.2f} sec')

5、 整合所有組件

# 4、整合所有組件
def load_data_fashion_mnist(batch_size, resize=None):"""下載Fashion-MNIST數據集,然后將其加載到內存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0, transforms.Resize(resize))trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False, num_workers=get_dataloader_workers()))
# 測試整和組件功能
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype)break

完整代碼:

import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l# 1、通過框架中的內置函數,將Fashion-MNIST數據集下載并讀取到內存中
# 通過ToTensor實例將圖像數據從PIL類型變換成32位浮點數格式;并除以255使得所有像素的數值均在0到1之間
trans = transforms.ToTensor()  # 預處理,用于將圖片轉為tensor
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)  # 在torchvision.datasets找到FashionMNIST數據集,參數:root="../data"下載目錄, train=True下載訓練數據集, transform=trans圖片轉為pytorch的tensor, download=True下載
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)
print("len(mnist_train):", len(mnist_train), "\nlen(mnist_test):", len(mnist_test))
print("mnist_train[0][0].shape,訓練集中第一張圖片的形狀:", mnist_train[0][0].shape, "\nmnist_train[0][1],訓練集中第一張圖片的標簽:", mnist_train[0][1])  # mnist_train[0][0]是圖片、mnist_train[0][1]是標簽# 2、兩個可視化數據集的函數,來畫一下數據集
def get_fashion_mnist_labels(labels):"""返回Fashion-MNIST數據集的文本標簽"""text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):"""繪制圖像列表"""figsize = (num_cols * scale, num_rows * scale)_, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)  # 使用subplots創建子圖axes = axes.flatten()for i, (ax, img) in enumerate(zip(axes, imgs)):if torch.is_tensor(img):ax.imshow(img.numpy())  # 圖片張量else:ax.imshow(img)  # PIL圖片ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])return axesX, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))  # 加載批量圖片
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y))  # 顯示圖片并添加標簽
# d2l.plt.show()  # 圖片在線展示# 3、讀取一小批量數據,大小batch_size
batch_size = 256
def get_dataloader_workers():"""使用4個進程來讀取的數據"""return 0  # 寫幾就是幾個進程train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers())
timer = d2l.Timer()
for X, y in train_iter:continue
print(f'{timer.stop():.2f} sec')'''
# 4、整合所有組件
def load_data_fashion_mnist(batch_size, resize=None):"""下載Fashion-MNIST數據集,然后將其加載到內存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0, transforms.Resize(resize))trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False, num_workers=get_dataloader_workers()))
# 測試整和組件功能
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype)break
'''

四、從零實現

1、導入庫

import torch
from IPython import display
from d2l import torch as d2l

2、數據集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)  # 每次讀取256張圖片,返回訓練集、測試集的迭代器:train_iter, test_iter# 將展平每個圖像1x28x28=784,將它們視為長度為784的向量(因為對于softmax回歸來講,輸入需要是一個向量)。因為我們的數據集有10個類別,所以網絡輸出維度為10
num_inputs = 784
num_outputs = 10

3、參數初始化

W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)  # 均值為0,方差為0.01初始化W權重
b = torch.zeros(num_outputs, requires_grad=True)  # 全0初始化

4、實現softmax

# 實現softmax
def softmax(X):X_exp = torch.exp(X)  # 對每一個元素做指數運算partition = X_exp.sum(1, keepdim=True)  # 按照維度為1來求和,對每一行求和;按行求和并保持維度不變,還是2維矩陣return X_exp / partition  # 這里應用了廣播機制,# 實現softmax回歸模型
def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)  # 對X reshape使其能夠與W做內積

?5、實現交叉熵損失函數

# 實現交叉熵損失函數
def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])

6、?將預測類別與真實y元素進行比較

def accuracy(y_hat, y):"""計算預測正確的數量"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = y_hat.argmax(axis=1)  # argmax返回每行最大值的索引cmp = y_hat.type(y.dtype) == y  # cmp為01向量,表示y_hat和y相同索引的個數return float(cmp.type(y.dtype).sum())  # 返回cmp中所有相同索引的和

7、?評估任意模型net的精度

# 我們可以評估任意模型net的精度
def evaluate_accuracy(net, data_iter):"""計算在指定數據集上模型的精度"""if isinstance(net, torch.nn.Module):net.eval()  # eval()停用dropout和batchnormmetric = Accumulator(2)  # 創建兩個元素的列表with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())  # 累加獲得預測正確的個數和總個數return metric[0] / metric[1]# Accumulator實例中創建了2個變量, 分別用于存儲正確預測的數量和預測的總數量
class Accumulator:"""在n個變量上累加"""def __init__(self, n):self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]  # 對數據累加def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]

8、Softmax回歸的訓練

# Softmax回歸的訓練
def train_epoch_ch3(net, train_iter, loss, updater):"""訓練模型一個迭代周期(定義見第3章)"""if isinstance(net, torch.nn.Module):  # 判斷是否自己實現函數net.train()metric = Accumulator(3)for X, y in train_iter:y_hat = net(X)l = loss(y_hat, y)if isinstance(updater, torch.optim.Optimizer):updater.zero_grad()l.sum().backward()updater.step()else:l.sum().backward()updater(X.shape[0])metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())return metric[0] / metric[2], metric[1] / metric[2]# 定義一個在動畫中繪制數據的實用程序類
class Animator:"""在動畫中繪制數據"""def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,figsize=(3.5, 2.5)):if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes, ]self.config_axes = lambda: d2l.set_axes(self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)]if not self.Y:self.Y = [[] for _ in range(n)]for i, (a, b) in enumerate(zip(x, y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)# 訓練函數
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):"""訓練模型(定義見第3章)"""animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],legend=['train loss', 'train acc', 'test acc'])for epoch in range(num_epochs):train_metrics = train_epoch_ch3(net, train_iter, loss, updater)test_acc = evaluate_accuracy(net, test_iter)animator.add(epoch + 1, train_metrics + (test_acc,))train_loss, train_acc = train_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_acc# 小批量隨機梯度下降來優化模型的損失函數
lr = 0.1
def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)# 訓練模型10個迭代周期
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater) # 調用前面的函數
d2l.plt.show()

?9、對圖像進行分類預測

# 對圖像進行分類預測
def predict_ch3(net, test_iter, n=6):"""預測標簽(定義見第3章)"""for X, y in test_iter:breaktrues = d2l.get_fashion_mnist_labels(y)preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))titles = [true +'\n' + pred for true, pred in zip(trues, preds)]d2l.show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])predict_ch3(net, test_iter)
d2l.plt.show()

完整代碼:

import torch
from IPython import display
from d2l import torch as d2l# softmax回歸的從零開始實現
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)  # 每次讀取256張圖片,返回訓練集、測試集的迭代器:train_iter, test_iter# 將展平每個圖像1x28x28=784,將它們視為長度為784的向量(因為對于softmax回歸來講,輸入需要是一個向量)。因為我們的數據集有10個類別,所以網絡輸出維度為10
num_inputs = 784
num_outputs = 10
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)  # 均值為0,方差為0.01初始化W權重
b = torch.zeros(num_outputs, requires_grad=True)  # 全0初始化# 實現softmax
def softmax(X):X_exp = torch.exp(X)  # 對每一個元素做指數運算partition = X_exp.sum(1, keepdim=True)  # 按照維度為1來求和,對每一行求和;按行求和并保持維度不變,還是2維矩陣return X_exp / partition  # 這里應用了廣播機制,# 實現softmax回歸模型
def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)  # 對X reshape使其能夠與W做內積# 實現交叉熵損失函數
def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])# 將預測類別與真實y元素進行比較
def accuracy(y_hat, y):"""計算預測正確的數量"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:y_hat = y_hat.argmax(axis=1)  # argmax返回每行最大值的索引cmp = y_hat.type(y.dtype) == y  # cmp為01向量,表示y_hat和y相同索引的個數return float(cmp.type(y.dtype).sum())  # 返回cmp中所有相同索引的和# 我們可以評估在任意模型net的精度
def evaluate_accuracy(net, data_iter):"""計算在指定數據集上模型的精度"""if isinstance(net, torch.nn.Module):net.eval()  # eval()停用dropout和batchnormmetric = Accumulator(2)  # 創建兩個元素的列表with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())  # 累加獲得預測正確的個數和總個數return metric[0] / metric[1]# Accumulator實例中創建了2個變量, 分別用于存儲正確預測的數量和預測的總數量
class Accumulator:"""在n個變量上累加"""def __init__(self, n):self.data = [0.0] * ndef add(self, *args):self.data = [a + float(b) for a, b in zip(self.data, args)]  # 對數據累加def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self, idx):return self.data[idx]# Softmax回歸的訓練
def train_epoch_ch3(net, train_iter, loss, updater):"""訓練模型一個迭代周期(定義見第3章)"""if isinstance(net, torch.nn.Module):  # 判斷是否自己實現函數net.train()metric = Accumulator(3)for X, y in train_iter:y_hat = net(X)l = loss(y_hat, y)if isinstance(updater, torch.optim.Optimizer):updater.zero_grad()l.sum().backward()updater.step()else:l.sum().backward()updater(X.shape[0])metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())return metric[0] / metric[2], metric[1] / metric[2]# 定義一個在動畫中繪制數據的實用程序類
class Animator:"""在動畫中繪制數據"""def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,figsize=(3.5, 2.5)):if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes, ]self.config_axes = lambda: d2l.set_axes(self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)]if not self.Y:self.Y = [[] for _ in range(n)]for i, (a, b) in enumerate(zip(x, y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)# 訓練函數
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):"""訓練模型(定義見第3章)"""animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],legend=['train loss', 'train acc', 'test acc'])for epoch in range(num_epochs):train_metrics = train_epoch_ch3(net, train_iter, loss, updater)test_acc = evaluate_accuracy(net, test_iter)animator.add(epoch + 1, train_metrics + (test_acc,))train_loss, train_acc = train_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_acc# 小批量隨機梯度下降來優化模型的損失函數
lr = 0.1
def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)# 訓練模型10個迭代周期
num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater) # 調用前面的函數
d2l.plt.show()# 對圖像進行分類預測
def predict_ch3(net, test_iter, n=6):"""預測標簽(定義見第3章)"""for X, y in test_iter:breaktrues = d2l.get_fashion_mnist_labels(y)preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))titles = [true +'\n' + pred for true, pred in zip(trues, preds)]d2l.show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])predict_ch3(net, test_iter)
d2l.plt.show()

五、簡潔實現?

1、導入庫

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn

2、?人造數據集,使用線性模型參數 w = [2, -3.4]T、b = 4.2;得到features, labels

# 1、人造數據集,使用線性模型參數 w = [2, -3.4]T、b = 4.2;得到features, labels
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)def load_array(data_arrays, batch_size, is_train=True):"""構造一個Pytorch數據迭代"""dataset = data.TensorDataset(*data_arrays)  # 得到數據集,*表示接受任意多個參數并將其放在一個元組中,拆包return data.DataLoader(dataset, batch_size, shuffle=is_train)  # 加載數據集,shuffle表示是否隨機打亂batch_size = 10
data_iter = load_array(data_arrays=(features, labels), batch_size=batch_size)  # 把features, labels做成一個list傳入到data.TensorDataset,得到數據集datasetprint(next(iter(data_iter)))

3、?模型定義;'nn'是神經網絡的縮寫

# 2、模型定義;'nn'是神經網絡的縮寫
# (1)使用框架的預定義好的層
net = nn.Sequential(nn.Linear(2, 1))  # 指定輸入維度為2,輸出維度為1# (2)初始化模型參數
net[0].weight.data.normal_(0, 0.01)  # 就是對w初始化化為均值為0,方差為0.01的正態分布
net[0].bias.data.fill_(0)  # 就是對b初始化為0

4、?計算均方誤差使用的是MSELoss類,也稱為 平方范數

# 3、計算均方誤差使用的是MSELoss類,也稱為 平方范數
loss = nn.MSELoss()

5、?實例化SGD實例,優化器

# 4、實例化SGD實例,優化器
trainer = torch.optim.SGD(net.parameters(), lr=0.03)  # 傳入參數、學習率

6、?訓練過程

# 5、訓練過程
# (1)超參數設置
num_epochs = 3  # 整個數據掃三遍
# (2)訓練的實現大同小異,一般就是兩層for循環:第一層是每一次對數據掃一遍;第二層是對于每一次拿出一個批量大小的X、y
for epoch in range(num_epochs):for X, y in data_iter:l = loss(net(X), y)  # 把 X 放到模型里面做預測(net本身自己帶了模型參數,所以不需要w、b再傳入了);把 預測的y 與 真實的y 做損失;得到的損失就是 一個批量大小的向量trainer.zero_grad()  # 優化器梯度清0l.backward()  # 求梯度,此處不用求sum,因為已經自動求完sum了trainer.step()  # 調用step()函數,進行一次模型參數的更新# 對數據掃完一邊之后,評價一下進度,此時是不需要梯度的,l = loss(net(features), labels)print(f"epoch {epoch + 1}, loss {l:f}") # 打印評估的結果

完整代碼:

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn# 線性回歸的簡潔實現(使用深度學習框架提供的計算);包括數據流水線、模型、損失函數和小批量隨機梯度下降優化器
# 1、人造數據集,使用線性模型參數 w = [2, -3.4]T、b = 4.2;得到features, labels
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)def load_array(data_arrays, batch_size, is_train=True):"""構造一個Pytorch數據迭代"""dataset = data.TensorDataset(*data_arrays)  # 得到數據集,*表示接受任意多個參數并將其放在一個元組中,拆包return data.DataLoader(dataset, batch_size, shuffle=is_train)  # 加載數據集,shuffle表示是否隨機打亂batch_size = 10
data_iter = load_array(data_arrays=(features, labels), batch_size=batch_size)  # 把features, labels做成一個list傳入到data.TensorDataset,得到數據集datasetprint(next(iter(data_iter)))# 2、模型定義;'nn'是神經網絡的縮寫
# (1)使用框架的預定義好的層
net = nn.Sequential(nn.Linear(2, 1))  # 指定輸入維度為2,輸出維度為1# (2)初始化模型參數
net[0].weight.data.normal_(0, 0.01)  # 就是對w初始化化為均值為0,方差為0.01的正態分布
net[0].bias.data.fill_(0)  # 就是對b初始化為0# 3、計算均方誤差使用的是MSELoss類,也稱為 平方范數
loss = nn.MSELoss()# 4、實例化SGD實例,優化器
trainer = torch.optim.SGD(net.parameters(), lr=0.03)  # 傳入參數、學習率# 5、訓練過程
# (1)超參數設置
num_epochs = 3  # 整個數據掃三遍
# (2)訓練的實現大同小異,一般就是兩層for循環:第一層是每一次對數據掃一遍;第二層是對于每一次拿出一個批量大小的X、y
for epoch in range(num_epochs):for X, y in data_iter:l = loss(net(X), y)  # 把 X 放到模型里面做預測(net本身自己帶了模型參數,所以不需要w、b再傳入了);把 預測的y 與 真實的y 做損失;得到的損失就是 一個批量大小的向量trainer.zero_grad()  # 優化器梯度清0l.backward()  # 求梯度,此處不用求sum,因為已經自動求完sum了trainer.step()  # 調用step()函數,進行一次模型參數的更新# 對數據掃完一邊之后,評價一下進度,此時是不需要梯度的,l = loss(net(features), labels)print(f"epoch {epoch + 1}, loss {l:f}") # 打印評估的結果

如果此文章對您有所幫助,那就請點個贊吧,收藏+關注 那就更棒啦,十分感謝!!!?

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

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

相關文章

C++八股——內存分配

文章目錄 1. 虛擬內存空間2. malloc和free3. new和delete4. 內存池 1. 虛擬內存空間 程序進程的虛擬內存空間是操作系統為每個進程提供的獨立、連續的邏輯地址空間&#xff0c;與物理內存解耦。其核心目的是隔離進程、簡化內存管理&#xff0c;并提供靈活的內存訪問控制。 &am…

【Linux基礎】網絡相關命令

目錄 netstat命令 1.1 命令介紹 1.2 命令格式 1.3 常用選項 1.4 常用命令實例 1.4.1 顯示所有TCP連接 1.4.2 查看路由表 1.4.3 實時監控網絡接口流量 1.4.4 查看監聽中的端口以及關聯進程 ping命令 2.1 命令介紹 2.2 命令格式 2.3 常用選項 2.4 常用示例 ifconfi…

adb 實用命令匯總

版權歸作者所有&#xff0c;如有轉發&#xff0c;請注明文章出處&#xff1a;https://cyrus-studio.github.io/blog/ 基礎adb命令 # 重啟adb adb kill-server# 查看已連接的設備 adb devices# 進入命令行 adb shell# 使用 -s 參數來指定設備 adb -s <設備序列號> shell…

C#管道通訊及傳輸信息丟失的原因

以下是C#管道通訊客戶端/服務端共用類 namespace PipeCommunication { /// <summary> /// 管道信息回調通知 /// </summary> /// <param name"msg"></param> public delegate void PipeMessageEventHandler(string msg…

MixTeX - 支持CPU推理的多模態LaTeX OCR

文章目錄 一、項目概覽相關資源核心特性技術特點 二、安裝三、使用說明環境要求 四、版本更新五、當前限制 一、項目概覽 MixTeX是一款創新的多模態LaTeX識別小程序&#xff0c;支持本地離線環境下的高效CPU推理。 無論是LaTeX公式、表格還是混合文本&#xff0c;MixTeX都能輕…

簡單 Linux 字符設備驅動程序

注&#xff1a;本文為 “Linux 字符設備驅動” 相關文章合輯。 英文引文&#xff0c;機翻未校。 中文引文&#xff0c;略作重排。 未整理去重&#xff0c;如有內容異常&#xff0c;請看原文。 Simple Linux character device driver 簡單 Linux 字符設備驅動程序 Oleg Kutko…

NX949NX952美光科技閃存NX961NX964

NX949NX952美光科技閃存NX961NX964 在半導體存儲領域&#xff0c;美光科技始終扮演著技術引領者的角色。其NX系列閃存產品線憑借卓越的性能與創新設計&#xff0c;成為數據中心、人工智能、高端消費電子等場景的核心組件。本文將圍繞NX949、NX952、NX961及NX964四款代表性產品…

協議路由與路由協議

協議路由”和“路由協議”聽起來相似&#xff0c;但其實是兩個完全不同的網絡概念。下面我來分別解釋&#xff1a; 一、協議路由&#xff08;Policy-Based Routing&#xff0c;PBR&#xff09; ? 定義&#xff1a; 協議路由是指 根據預設策略&#xff08;策略路由&#xff0…

Linux510 ssh服務 ssh連接

arning: Permanently added ‘11.1.1.100’ (ECDSA) to the list of known hosts. rooot11.1.1.100’s password: Permission denied, please try again. rooot11.1.1.100’s password: Permission denied, please try again 還沒生效 登不上了 失效了 sshcaozx26成功登錄 …

金融學知識筆記

金融學知識筆記 一、引言 金融學它結合了數學、概率論、統計學、經濟學和計算機科學等多學科的知識&#xff0c;用于解決金融領域中的各種問題&#xff0c;如金融衍生品定價、投資組合優化、風險管理和固定收益證券分析等。通過對金融學的學習&#xff0c;我們可以更好地理解…

AB測試面試題

AB測試面試題 常考AB測試問答題(1)AB測試的優缺點是什么?(2)AB測試的一般流程/介紹一下日常工作中你是如何做A/B實驗的?(3)第一類錯誤 vs 第二類錯誤 vs 你怎么理解AB測試中的第一、二類錯誤?(4)統計顯著=實際顯著?(5)AB測試效果統計上不顯著?(6)實驗組優于對…

USR-M100采集數據并提交MQTT服務器

本文為記錄備忘&#xff0c;不做過多解釋。 模塊自身帶有2路數字量輸入&#xff0c;2路模擬量輸入&#xff0c;2路485接口 數字量接報警輸入&#xff0c;模擬量接壓力傳感器&#xff0c;液位傳感器&#xff0c;485接口分別接流量計&#xff0c;溫濕度傳感器。 正確接線&…

Octave 繪圖快速入門指南

目錄 1. 基本的 2D 繪圖 2. 自定義圖形樣式 3. 繪制散點圖 4. 繪制柱狀圖 5. 繪制直方圖 6. 3D 繪圖 6.6.1 3D 曲面圖 6.6.2 3D 散點圖 7. 繪制極坐標 8. 多子圖繪制 總結 Octave 是一個類似于 MATLAB 的開源數學軟件&#xff0c;廣泛用于數值計算和數據分析。它提供…

RabbitMQ--基礎篇

RabbitMQ 簡介&#xff1a;RabbitMQ 是一種開源的消息隊列中間件&#xff0c;你可以把它想象成一個高效的“郵局”。它專門負責在不同應用程序之間傳遞消息&#xff0c;讓系統各部分能松耦合地協作 優勢&#xff1a; 異步處理&#xff1a;比如用戶注冊后&#xff0c;主程序將發…

【MySQL】事務(重點)

目錄 一、什么是事務&#xff1a; 二、事務的前置知識了解 引擎是否支持事務 事務的提交方式 事務操作的前置準備&#xff1a; 三、事務回滾&#xff1a; 四、事務崩潰&#xff1a; 原子性&#xff1a; 持久性&#xff1a; 五、自動提交和手動提交&#xff1a; 六、…

C++STL——stack,queue

stack與queue 前言容器適配器deque 前言 本篇主要講解stack與queue的底層&#xff0c;但并不會進行實現&#xff0c;stack的接口 queue的接口 &#xff0c;關于stack與queue的接口在這里不做講解&#xff0c;因為通過前面的對STL的學習&#xff0c;這些接口都是大同小異的。 …

STM32智能手表:基于FreeRTOS

引言 隨著物聯網和可穿戴設備的快速發展&#xff0c;智能手表作為典型代表&#xff0c;集成了傳感器數據采集、實時顯示、無線通信等多項功能。本文將深入剖析一個基于STM32和FreeRTOS的智能手表項目&#xff0c;從硬件架構到軟件設計&#xff0c;逐步講解如何構建一個完整的嵌…

leetcode504.七進制數

標簽&#xff1a;進制轉換 機試真題 給定一個整數 num&#xff0c;將其轉化為 7 進制&#xff0c;并以字符串形式輸出。 示例 1: 輸入: num 100 輸出: "202" 示例 2: 輸入: num -7 輸出: "-10" 思路&#xff1a;求n進制就是循環取余數&#xff0c;…

中國古代史2

夏朝&#xff08;公元前2070-公元前1600年&#xff09; 1.禹建立了我國歷史上第一個奴隸制國家–夏朝&#xff0c;定都陽城。禹傳啟&#xff0c;世襲制代替禪讓制。 2.夏代都城&#xff1a;二里頭遺址位于今河南洛陽偃師二里頭村。發現了大型綠松石龍形器&#xff0c;被命名為…

死鎖的形成

死鎖的形成 背景學習資源死鎖的本質 背景 面試可能會被問到. 學習資源 一個案例: https://www.bilibili.com/video/BV1pz421Y7kM 死鎖的本質 互相持有對方的資源. 存在資源競爭都沒有釋放. 可能出現死鎖. insert into demo_user (no, name) values (6, ‘test1’) on dupl…