一 保存最優模型
主要就是我們在for循環中加上一個test測試,并且我還在test函數后面加上了返回值,可以返回準確率,然后每次進行一次對比,然后取大的。然后這里有兩種保存方式,一種是保存了整個模型,另一個是保存了模型參數。
1 僅保存模型參數
torch.save(model.state_dict(),'best_model.pth')
然后后面我們使用的時候
model =torch.load('best1.pth')#
model.to(device)
model.load_state_dict(torch.load("best.pth", map_location=device))
model.eval()
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
test(test_dataloader,model,loss_fn)
注意這里要設置eval模式,因為我們要保證我們的模型參數不再變化了。
2 保存整個模型
torch.save(model,'best1.pth')
在調用的時候
model = torch.load('best1.pth', map_location=torch.device('cuda'))
model.eval()
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
test(test_dataloader,model,loss_fn)
直接調用就好。
注意這兩種必須要有定義好的網絡,不然無法運行(保存整個網絡也要定于一個完全相同的網絡)。
完整代碼
epochs=20
for i in range(epochs):print(f"Epoch {i+1}")train(train_dataloader,model,loss_fn,optimizer)corrects = test(test_dataloader,model,loss_fn)accuracy_list.append(corrects)if corrects>best_acc:print(f"Best Accuracy: {corrects}%")best_acc=corrects#第一種# torch.save(model.state_dict(),'best_model.pth')#第二種torch.save(model,'best1.pth')
完整代碼含網絡
import numpy as np
import torch
from PIL import Image
from torch import nn
from torch.utils.data import DataLoader, Dataset
from torchvision import transformsclass CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.conv1 = nn.Sequential(nn.Conv2d( # 2d一般用于圖像,3d用于視頻數據(多一個時間維度),1d一般用于結構化的序列數據in_channels=3, # 圖像通道個數,1表示灰度圖(確定了卷積核 組中的個數),out_channels=16, # 要得到多少個特征圖,卷積核的個數kernel_size=5, # 卷積核人小,5*5stride=1, # 步長padding=2 # 填充值),nn.ReLU(),nn.MaxPool2d(kernel_size=2), # 進行池化操作(2x2 區域))self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2),nn.ReLU(),nn.Conv2d(32, 32, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(kernel_size=2),)self.conv3 = nn.Sequential(nn.Conv2d(32, 64, 5, 1, 2),nn.ReLU(),)self.out = nn.Linear(64 * 64 * 64, 20) # 全連接層得到的結果def forward(self, x): # 前向傳播,你得告訴它 數據的流向 是神經網絡層連接起來,函數名稱不能改x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = x.view(x.size(0), -1) # view和reshape是一樣的作用,但此處是tensor形式output = self.out(x)return outputdata_transform={# 'train': transforms.Compose([# # 調整圖像大小為300x300像素# transforms.Resize([256, 256]),## # # 隨機旋轉:-45到45度之間隨機選擇角度# # transforms.RandomRotation(45),# # ## # # # 從中心裁剪出256x256的區域# # transforms.CenterCrop([256, 256]),# ## # # 隨機水平翻轉:以50%的概率進行水平鏡像# # transforms.RandomHorizontalFlip(p=0.5),# ## # # 隨機垂直翻轉:以50%的概率進行垂直鏡像# # transforms.RandomVerticalFlip(p=0.5),# ## # # # 顏色抖動:隨機調整亮度、對比度、飽和度和色調# # # transforms.ColorJitter(# # # brightness=0.2, # 亮度變化幅度為20%# # # contrast=0.1, # 對比度變化幅度為10%# # # saturation=0.1, # 飽和度變化幅度為10%# # # hue=0.1 # 色調變化幅度為10%# # # ),# # ## # # # 隨機灰度化:以10%的概率將圖像轉換為灰度圖# # transforms.RandomGrayscale(p=0.1),## # 將PIL圖像轉換為PyTorch張量,并自動歸一化到[0,1]范圍# transforms.ToTensor(),## # 標準化:使用ImageNet數據集的均值和標準差進行標準化# transforms.Normalize(# [0.485, 0.456, 0.406], # 均值(R, G, B通道)# [0.229, 0.224, 0.225] # 標準差(R, G, B通道)# )# ]),# 驗證/測試數據的預處理(通常不需要數據增強)'test': transforms.Compose([transforms.Resize([256, 256]),# transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
}class food_dataset(Dataset):def __init__(self, root, transform=None):super().__init__()self.root = rootself.transform = transformself.images = []self.labels = []with open(root,encoding='utf-8') as f:samples = [i.strip().split() for i in f.readlines()]for img_path,label in samples:self.images.append(img_path)self.labels.append(label)def __len__(self):return len(self.images)def __getitem__(self, index):image=Image.open(self.images[index]).convert('RGB')if self.transform:image=self.transform(image)label = self.labels[index]# print(label)label = torch.from_numpy(np.array(label,dtype=np.int64))# print(label)return image, labeldef test(dataloader,model,loss_fn):size = len(dataloader.dataset)num_batches = len(dataloader)model.eval()batch_size_num=1loss,correct=0,0with torch.no_grad():for X, y in test_dataloader:X,y=X.to(device),y.to(device)pred = model(X)loss = loss_fn(pred,y)+losscorrect += (pred.argmax(1) == y).type(torch.float).sum().item()loss/=num_batchescorrect/=sizeprint(f'Test result: \n Accuracy: {(100*correct)}%,Avg loss: {loss}')device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")test_data=food_dataset('test_data',transform=(data_transform['test']))
test_dataloader = DataLoader(test_data, batch_size=16, shuffle=True)# model =CNN()
# model.to(device)
# model.load_state_dict(torch.load("best.pth"))
model=torch.load('best.pt')
model.eval()
loss_fn = nn.CrossEntropyLoss()
test(test_dataloader,model,loss_fn)