早停策略和模型權重的保存

知識點回顧:

  1. 過擬合的判斷:測試集和訓練集同步打印指標
  2. 模型的保存和加載
    1. 僅保存權重
    2. 保存權重和模型
    3. 保存全部信息checkpoint,還包含訓練狀態
  3. 早停策略

作業:對信貸數據集訓練后保存權重,加載權重后繼續訓練50輪,并采取早停策略

import pandas as pd  # 用于數據處理和分析,可處理表格數據。
import numpy as np  # 用于數值計算,提供了高效的數組操作。
import matplotlib.pyplot as plt  # 用于繪制各種類型的圖表
import seaborn as sns  # 基于matplotlib的高級繪圖庫,能繪制更美觀的統計圖形。
import warningswarnings.filterwarnings("ignore")# 設置中文字體(解決中文顯示問題)
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系統常用黑體字體
plt.rcParams['axes.unicode_minus'] = False  # 正常顯示負號
data = pd.read_excel('data.xlsx')  # 讀取數據# 先篩選字符串變量
discrete_features = data.select_dtypes(include=['object']).columns.tolist()
# Home Ownership 標簽編碼
home_ownership_mapping = {'Own Home': 1,'Rent': 2,'Have Mortgage': 3,'Home Mortgage': 4
}
data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping)# Years in current job 標簽編碼
years_in_job_mapping = {'< 1 year': 1,'1 year': 2,'2 years': 3,'3 years': 4,'4 years': 5,'5 years': 6,'6 years': 7,'7 years': 8,'8 years': 9,'9 years': 10,'10+ years': 11
}
data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping)# Purpose 獨熱編碼,記得需要將bool類型轉換為數值
data = pd.get_dummies(data, columns=['Purpose'])
data2 = pd.read_excel("data.xlsx")  # 重新讀取數據,用來做列名對比
list_final = []  # 新建一個空列表,用于存放獨熱編碼后新增的特征名
for i in data.columns:if i not in data2.columns:list_final.append(i)  # 這里打印出來的就是獨熱編碼后的特征名
for i in list_final:data[i] = data[i].astype(int)  # 這里的i就是獨熱編碼后的特征名# Term 0 - 1 映射
term_mapping = {'Short Term': 0,'Long Term': 1
}
data['Term'] = data['Term'].map(term_mapping)
data.rename(columns={'Term': 'Long Term'}, inplace=True)  # 重命名列
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist()  # 把篩選出來的列名轉換成列表# 連續特征用中位數補全
for feature in continuous_features:mode_value = data[feature].mode()[0]  # 獲取該列的眾數。data[feature].fillna(mode_value, inplace=True)  # 用眾數填充該列的缺失值,inplace=True表示直接在原數據上修改。

?第一次訓練:

import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import time
import matplotlib.pyplot as plt
from tqdm import tqdm  # 導入tqdm庫用于進度條顯示# 設置GPU設備
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用設備: {device}")from sklearn.model_selection import train_test_splitX = data.drop(['Credit Default'], axis=1)  # 特征,axis=1表示按列刪除
y = data['Credit Default']  # 標簽# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 歸一化數據
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)# 將數據轉換為PyTorch張量并移至GPU
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train.values).to(device)  # 添加 .values
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test.values).to(device)  # 添加 .values
class MLP(nn.Module):def __init__(self,input_size):super(MLP, self).__init__()self.fc1 = nn.Linear(input_size, 10)  # 輸入層到隱藏層self.relu = nn.ReLU()self.fc2 = nn.Linear(10, 2)  # 隱藏層到輸出層def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# 實例化模型并移至GPU
model = MLP(input_size= X_train.shape[1]).to(device)# 分類問題使用交叉熵損失函數
criterion = nn.CrossEntropyLoss()# 使用隨機梯度下降優化器
optimizer = optim.SGD(model.parameters(), lr=0.01)# 訓練模型
num_epochs = 30000  # 訓練的輪數# 用于存儲每100個epoch的損失值和對應的epoch數
losses = []
epochs = []start_time = time.time()  # 記錄開始時間# 創建tqdm進度條
with tqdm(total=num_epochs, desc="訓練進度", unit="epoch") as pbar:# 訓練模型for epoch in range(num_epochs):# 前向傳播outputs = model(X_train)  # 隱式調用forward函數loss = criterion(outputs, y_train)# 反向傳播和優化optimizer.zero_grad()loss.backward()optimizer.step()# 記錄損失值并更新進度條if (epoch + 1) % 200 == 0:losses.append(loss.item())epochs.append(epoch + 1)# 更新進度條的描述信息pbar.set_postfix({'Loss': f'{loss.item():.4f}'})# 每1000個epoch更新一次進度條if (epoch + 1) % 1000 == 0:pbar.update(1000)  # 更新進度條# 確保進度條達到100%if pbar.n < num_epochs:pbar.update(num_epochs - pbar.n)  # 計算剩余的進度并更新time_all = time.time() - start_time  # 計算訓練時間
print(f'1st Training time: {time_all:.2f} seconds')torch.save({'model_state_dict': model.state_dict(),'optimizer_state_dict': optimizer.state_dict(),
}, "checkpoint.pth")

使用設備: cpu

訓練進度: 100%|██████████| 30000/30000 [00:22<00:00, 1322.08epoch/s, Loss=0.4614]

1st Training time: 22.70 seconds

第二次訓練(增加早停):

# 重新實例化模型并加載參數
model = MLP(input_size=X_train.shape[1]).to(device)
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 必須在加載優化器前定義好# 加載模型和優化器狀態
checkpoint = torch.load("checkpoint.pth")
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])num_plus_epochs = 50  # 訓練的輪數
# 用于存儲每200個epoch的損失值和對應的epoch數
train_losses = []  # 存儲訓練集損失
test_losses = []  # 存儲測試集損失
epochs = []# ===== 新增早停相關參數 =====
best_test_loss = float('inf')  # 記錄最佳測試集損失
best_epoch = 0  # 記錄最佳epoch
patience = 1  # 早停耐心值(連續多少輪測試集損失未改善時停止訓練)
counter = 0  # 早停計數器
early_stopped = False  # 是否早停標志
# ==========================start_time = time.time()  # 記錄開始時間# 創建tqdm進度條
with tqdm(total=num_plus_epochs, desc="訓練進度plus", unit="epoch") as pbar:# 訓練模型for epoch in range(num_plus_epochs):# 前向傳播outputs = model(X_train)  # 隱式調用forward函數train_loss = criterion(outputs, y_train)# 反向傳播和優化optimizer.zero_grad()train_loss.backward()optimizer.step()train_losses.append(train_loss.item())# 記錄損失值并更新進度條model.eval()with torch.no_grad():test_outputs = model(X_test)test_loss = criterion(test_outputs, y_test)model.train()test_losses.append(test_loss.item())epochs.append(epoch + 1)# 更新進度條的描述信息pbar.set_postfix({'Train Loss': f'{train_loss.item():.4f}', 'Test Loss': f'{test_loss.item():.4f}'})# ===== 新增早停邏輯 =====if test_loss.item() < best_test_loss:  # 如果當前測試集損失小于最佳損失best_test_loss = test_loss.item()  # 更新最佳損失best_epoch = epoch + 1  # 更新最佳epochcounter = 0  # 重置計數器# 保存最佳模型torch.save(model.state_dict(), 'best_model.pth')else:counter += 1if counter >= patience:print(f"早停觸發!在第{epoch + 1}輪,測試集損失已有{patience}輪未改善。")print(f"最佳測試集損失出現在第{best_epoch}輪,損失值為{best_test_loss:.4f}")early_stopped = Truebreak  # 終止訓練循環# ======================pbar.update(1)  # 更新進度條# 確保進度條達到100%if pbar.n < num_plus_epochs:pbar.update(num_plus_epochs - pbar.n)  # 計算剩余的進度并更新time_all = time.time() - start_time  # 計算訓練時間
print(f'Training time: {time_all:.2f} seconds')# ===== 新增:加載最佳模型用于最終評估 =====
if early_stopped:print(f"加載第{best_epoch}輪的最佳模型進行最終評估...")model.load_state_dict(torch.load('best_model.pth'))
# ================================# 可視化損失曲線
plt.figure(figsize=(10, 6))
plt.plot(epochs, train_losses, label='Train Loss')
plt.plot(epochs, test_losses, label='Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training and Test Loss over Epochs')
plt.legend()
plt.grid(True)
plt.show()

訓練進度plus: 100%|██████████| 50/50 [00:00<00:00, 648.00epoch/s, Train Loss=0.4614, Test Loss=0.4713]

早停觸發!在第8輪,測試集損失已有1輪未改善。 最佳測試集損失出現在第7輪,損失值為0.4713 Training time: 0.09 seconds 加載第7輪的最佳模型進行最終評估...

?

測試:?

model.eval() # 設置模型為評估模式
with torch.no_grad(): # torch.no_grad()的作用是禁用梯度計算,可以提高模型推理速度outputs = model(X_test)  # 對測試數據進行前向傳播,獲得預測結果_, predicted = torch.max(outputs, 1) # torch.max(outputs, 1)返回每行的最大值和對應的索引#這個函數返回2個值,分別是最大值和對應索引,參數1是在第1維度(行)上找最大值,_ 是Python的約定,表示忽略這個返回值,所以這個寫法是找到每一行最大值的下標# 此時outputs是一個tensor,p每一行是一個樣本,每一行有3個值,分別是屬于3個類別的概率,取最大值的下標就是預測的類別# predicted == y_test判斷預測值和真實值是否相等,返回一個tensor,1表示相等,0表示不等,然后求和,再除以y_test.size(0)得到準確率# 因為這個時候數據是tensor,所以需要用item()方法將tensor轉化為Python的標量# 之所以不用sklearn的accuracy_score函數,是因為這個函數是在CPU上運行的,需要將數據轉移到CPU上,這樣會慢一些# size(0)獲取第0維的長度,即樣本數量correct = (predicted == y_test).sum().item() # 計算預測正確的樣本數accuracy = correct / y_test.size(0)print(f'測試集準確率: {accuracy * 100:.2f}%')

?測試集準確率: 76.67%

@浙大疏錦行

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

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

相關文章

DeepSpeed-Ulysses:支持極長序列 Transformer 模型訓練的系統優化方法

DeepSpeed-Ulysses&#xff1a;支持極長序列 Transformer 模型訓練的系統優化方法 flyfish 名字 Ulysses “Ulysses” 和 “奧德修斯&#xff08;Odysseus&#xff09;” 指的是同一人物&#xff0c;“Ulysses” 是 “Odysseus” 的拉丁化版本 《尤利西斯》&#xff08;詹姆…

Redis-基礎-總結

一、概述 Remote Dictionary Server(遠程字典服務)是完全開源的&#xff0c;使用ANSIC語言編寫遵守BSD協議&#xff0c;是一個高性能的Key-Value數據庫提供了豐富的數據結構&#xff0c;例如String、Hash、List、Set、sortedset等等。數據是存在內存中的&#xff0c;同時Redis…

尚硅谷redis7 28-32 redis持久化之理論介紹

28redis持久化之理論介紹 redis持久化&#xff1a;redis如何將內存數據寫入磁盤中 為什么需要持久化&#xff1f; 內存數據一斷電就會消失&#xff0c;那么所有的請求都會打到數據庫中。因此讓redis中的數據長期持有&#xff0c;不管是重啟、故障、恢復、宕機&#xff0c;還…

JS逆向【抖查查】逆向分析 | sign | secret簽名驗證

1.目標 目標網址&#xff1a;https://www.douchacha.com/bloggerRankingRise 切換日期出現目標請求 import requests import jsonheaders {"accept": "application/json, text/plain, */*","accept-language": "zh-CN,zh;q0.9","…

【數據倉庫面試題合集④】SQL 性能調優:面試高頻場景 + 調優策略解析

隨著業務數據規模的持續增長,SQL 查詢的執行效率直接影響到數據平臺的穩定性與數據產出效率。因此,在數據倉庫類崗位的面試中,SQL 性能調優常被作為重點考察內容。 本篇將圍繞常見 SQL 調優問題,結合實際經驗,整理出高頻面試題與答題參考,助你在面試中游刃有余。 ?? 高…

python打卡訓練營打卡記錄day37

知識點回顧&#xff1a; 過擬合的判斷&#xff1a;測試集和訓練集同步打印指標模型的保存和加載 僅保存權重保存權重和模型保存全部信息checkpoint&#xff0c;還包含訓練狀態 早停策略 作業&#xff1a;對信貸數據集訓練后保存權重&#xff0c;加載權重后繼續訓練50輪&#xf…

卷積神經網絡(CNN)深度講解

卷積神經網絡&#xff08;CNN&#xff09; 本篇博客參考自大佬的開源書籍&#xff0c;幫助大家從頭開始學習卷積神經網絡&#xff0c;謝謝各位的支持了&#xff0c;在此期待各位能與我共同進步? 卷積神經網絡&#xff08;CNN&#xff09;是一種特殊的深度學習網絡結構&#x…

深度體驗:海螺 AI,開啟智能創作新時代

人工智能 AI 工具如雨后春筍般涌現&#xff0c;而海螺 AI 以其獨特的魅力與卓越的性能&#xff0c;迅速在眾多產品中嶄露頭角&#xff0c;成為了無數創作者、辦公族以及各行業人士的得力助手。近期&#xff0c;我對海螺 AI 進行了深入的使用體驗&#xff0c;接下來就為大家詳細…

哈希表day5

242 有效的字母異位詞 思路就是轉為ASCII碼&#xff0c;然后用一個數組記錄26位字母出現的次數 #include <string> class Solution{ public:bool isAnagram(string s,string t){int record[26]{0};for (int i0;i<s.size();i){record[s[i]-a];}for (int i0;i<t.si…

【Python數據庫全棧指南】從SQL到ORM深度實踐

目錄 &#x1f31f; 前言&#x1f3d7;? 技術背景與價值&#x1fa79; 當前技術痛點&#x1f6e0;? 解決方案概述&#x1f465; 目標讀者說明 &#x1f9e0; 一、技術原理剖析&#x1f4ca; 核心概念圖解&#x1f4a1; 核心作用講解&#x1f527; 關鍵技術模塊說明?? 技術選…

Android磁盤占用優化全解析:從監控到治理的存儲效率革命

引言 隨著移動應用功能的復雜化&#xff0c;磁盤占用問題日益突出。據統計&#xff0c;國內頭部應用的平均安裝包大小已超100MB&#xff0c;運行時緩存、日志、圖片等數據更可能使磁盤占用突破GB級。過度的磁盤消耗不僅影響用戶設備空間&#xff0c;還可能觸發系統的“應用數據…

AJAX-讓數據活起來(一):入門

目錄 一、AJAX概念和axios使用 1.1 什么是AJAX ? 1.2 怎么用AJAX ? 1.3 axios使用 二、認識URL 2.1 什么是URL? 2.2 URL的組成 組成 協議 域名 資源路徑 獲取-新聞列表 三、URL查詢參數 URL查詢參數 axios - 查詢參數 四、常用請求方法和數據提交 常用請求…

【C++篇】list模擬實現

實現接口&#xff1a; list的無參構造、n個val構造、拷貝構造 operator重載 實現迭代器 push_back() push_front() erase() insert() 頭尾刪 #pragma once #include<iostream> #include<assert.h> using namespace std;namespace liu {//定義list節點temp…

Go 語言范圍循環變量重用問題與 VSCode 調試解決方法

文章目錄 問題描述問題原因1. Go 1.21 及更早版本的范圍循環行為2. Go 1.22 的改進3. VSCode 調試中的問題4. 命令行 dlv debug 的正確輸出 三種解決方法1. 啟用 Go 模塊2. 優化 VSCode 調試配置3. 修改代碼以確保兼容性4. 清理緩存5. 驗證環境 驗證結果結論 在 Go 編程中&…

快速創建 Vue 3 項目

安裝 Node.js 和 Vue CL 安裝 Node.js&#xff1a;訪問 https://nodejs.org/ 下載并安裝 LTS 版本。 安裝完后&#xff0c;在終端檢查版本&#xff1a; node -v npm -v安裝 Vue CLI&#xff08;全局&#xff09;&#xff1a; npm install -g vue/cli創建 Vue 3 項目 vue cr…

java學習日志——Spring Security介紹

使用Spring Security要重寫UserDetailsService的loadUserByUsername方法&#xff08;相當于自定了認證邏輯&#xff09;

【C++進階篇】初識哈希

哈希表深度剖析&#xff1a;原理、沖突解決與C容器實戰 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常見的哈希函數1.3.1 直接定址法1.3.2 除留余數法1.3.3 乘法散列法&#xff08;了解&#xff09;1.3.4 平方取中法&#xff08;了解&#xff09; 1.4 哈希沖突1.4.1 沖突原因1.4.2 解…

單機Kafka配置ssl并在springboot使用

目錄 SSL證書生成根證書生成服務端和客戶端證書生成keystore.jks和truststore.jks輔助腳本單獨生成truststore.jks 環境配置hosts文件kafka server.properties配置ssl 啟動kafkakafka基礎操作springboot集成準備工作需要配置的文件開始消費 SSL證書 證書主要包含兩大類&#x…

PCB設計教程【入門篇】——電路分析基礎-元件數據手冊

前言 本教程基于B站Expert電子實驗室的PCB設計教學的整理&#xff0c;為個人學習記錄&#xff0c;旨在幫助PCB設計新手入門。所有內容僅作學習交流使用&#xff0c;無任何商業目的。若涉及侵權&#xff0c;請隨時聯系&#xff0c;將會立即處理 目錄 前言 一、數據手冊的重要…

Vue2實現Office文檔(docx、xlsx、pdf)在線預覽

&#x1f31f; 前言 歡迎來到我的技術小宇宙&#xff01;&#x1f30c; 這里不僅是我記錄技術點滴的后花園&#xff0c;也是我分享學習心得和項目經驗的樂園。&#x1f4da; 無論你是技術小白還是資深大牛&#xff0c;這里總有一些內容能觸動你的好奇心。&#x1f50d; &#x…