pytorch實(shí)現(xiàn)好萊塢明星識(shí)別的示例代碼
一、前期準(zhǔn)備
1.設(shè)置GPU
import torch from torch import nn import torchvision from torchvision import transforms,datasets,models import matplotlib.pyplot as plt import os,PIL,pathlib
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
devicedevice(type='cuda')
2.導(dǎo)入數(shù)據(jù)
data_dir = './hlw/'
data_dir = pathlib.Path(data_dir)
data_paths = list(data_dir.glob('*'))
classNames = [str(path).split('\\')[1] for path in data_paths]
classNames['Angelina Jolie', 'Brad Pitt', 'Denzel Washington', 'Hugh Jackman', 'Jennifer Lawrence', 'Johnny Depp', 'Kate Winslet', 'Leonardo DiCaprio', 'Megan Fox', 'Natalie Portman', 'Nicole Kidman', 'Robert Downey Jr', 'Sandra Bullock', 'Scarlett Johansson', 'Tom Cruise', 'Tom Hanks', 'Will Smith']
train_transforms = transforms.Compose([
transforms.Resize([224,224]),# resize輸入圖片
transforms.ToTensor(), # 將PIL Image或numpy.ndarray轉(zhuǎn)換成tensor
transforms.Normalize(
mean = [0.485, 0.456, 0.406],
std = [0.229,0.224,0.225]) # 從數(shù)據(jù)集中隨機(jī)抽樣計(jì)算得到
])
total_data = datasets.ImageFolder(data_dir,transform=train_transforms)
total_dataDataset ImageFolder
Number of datapoints: 1800
Root location: hlw
StandardTransform
Transform: Compose(
Resize(size=[224, 224], interpolation=PIL.Image.BILINEAR)
ToTensor()
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
)3.數(shù)據(jù)集劃分
train_size = int(0.8*len(total_data)) test_size = len(total_data) - train_size train_dataset, test_dataset = torch.utils.data.random_split(total_data,[train_size,test_size]) train_dataset,test_dataset
(<torch.utils.data.dataset.Subset at 0x12f8aceda00>, <torch.utils.data.dataset.Subset at 0x12f8acedac0>)
train_size,test_size
(1440, 360)
batch_size = 32
train_dl = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=1)
test_dl = torch.utils.data.DataLoader(test_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=1)4. 數(shù)據(jù)可視化
imgs, labels = next(iter(train_dl)) imgs.shape
torch.Size([32, 3, 224, 224])
import numpy as np
# 指定圖片大小,圖像大小為20寬、5高的繪圖(單位為英寸inch)
plt.figure(figsize=(20, 5))
for i, imgs in enumerate(imgs[:20]):
npimg = imgs.numpy().transpose((1,2,0))
npimg = npimg * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))
npimg = npimg.clip(0, 1)
# 將整個(gè)figure分成2行10列,繪制第i+1個(gè)子圖。
plt.subplot(2, 10, i+1)
plt.imshow(npimg)
plt.axis('off')
for X,y in test_dl:
print('Shape of X [N, C, H, W]:', X.shape)
print('Shape of y:', y.shape)
breakShape of X [N, C, H, W]: torch.Size([32, 3, 224, 224])Shape of y: torch.Size([32])
二、構(gòu)建簡單的CNN網(wǎng)絡(luò)
from torchvision.models import vgg16
model = vgg16(pretrained = True).to(device)
for param in model.parameters():
param.requires_grad = False
model.classifier._modules['6'] = nn.Linear(4096,len(classNames))
model.to(device)
model
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(6): ReLU(inplace=True)
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU(inplace=True)
(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(11): ReLU(inplace=True)
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU(inplace=True)
(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(15): ReLU(inplace=True)
(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(18): ReLU(inplace=True)
(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(20): ReLU(inplace=True)
(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(22): ReLU(inplace=True)
(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(25): ReLU(inplace=True)
(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(27): ReLU(inplace=True)
(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(29): ReLU(inplace=True)
(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=17, bias=True)
)
)# 查看要訓(xùn)練的層
params_to_update = model.parameters()
# params_to_update = []
for name,param in model.named_parameters():
if param.requires_grad == True:
# params_to_update.append(param)
print("\t",name)三、訓(xùn)練模型
1.優(yōu)化器設(shè)置
# 優(yōu)化器設(shè)置 optimizer = torch.optim.Adam(params_to_update, lr=1e-4)#要訓(xùn)練什么參數(shù)/ scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.92)#學(xué)習(xí)率每5個(gè)epoch衰減成原來的1/10 loss_fn = nn.CrossEntropyLoss()
2.編寫訓(xùn)練函數(shù)
# 訓(xùn)練循環(huán)
def train(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) # 訓(xùn)練集的大小,一共900張圖片
num_batches = len(dataloader) # 批次數(shù)目,29(900/32)
train_loss, train_acc = 0, 0 # 初始化訓(xùn)練損失和正確率
for X, y in dataloader: # 獲取圖片及其標(biāo)簽
X, y = X.to(device), y.to(device)
# 計(jì)算預(yù)測誤差
pred = model(X) # 網(wǎng)絡(luò)輸出
loss = loss_fn(pred, y) # 計(jì)算網(wǎng)絡(luò)輸出和真實(shí)值之間的差距,targets為真實(shí)值,計(jì)算二者差值即為損失
# 反向傳播
optimizer.zero_grad() # grad屬性歸零
loss.backward() # 反向傳播
optimizer.step() # 每一步自動(dòng)更新
# 記錄acc與loss
train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()
train_loss += loss.item()
train_acc /= size
train_loss /= num_batches
return train_acc, train_loss3.編寫測試函數(shù)
def test (dataloader, model, loss_fn):
size = len(dataloader.dataset) # 測試集的大小,一共10000張圖片
num_batches = len(dataloader) # 批次數(shù)目,8(255/32=8,向上取整)
test_loss, test_acc = 0, 0
# 當(dāng)不進(jìn)行訓(xùn)練時(shí),停止梯度更新,節(jié)省計(jì)算內(nèi)存消耗
with torch.no_grad():
for imgs, target in dataloader:
imgs, target = imgs.to(device), target.to(device)
# 計(jì)算loss
target_pred = model(imgs)
loss = loss_fn(target_pred, target)
test_loss += loss.item()
test_acc += (target_pred.argmax(1) == target).type(torch.float).sum().item()
test_acc /= size
test_loss /= num_batches
return test_acc, test_loss4、正式訓(xùn)練
訓(xùn)練輸出層
epochs = 20
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_acc = 0
filename='checkpoint.pth'
for epoch in range(epochs):
model.train()
epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
scheduler.step()#學(xué)習(xí)率衰減
model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
# 保存最優(yōu)模型
if epoch_test_acc > best_acc:
best_acc = epoch_train_acc
state = {
'state_dict': model.state_dict(),#字典里key就是各層的名字,值就是訓(xùn)練好的權(quán)重
'best_acc': best_acc,
'optimizer' : optimizer.state_dict(),
}
torch.save(state, filename)
train_acc.append(epoch_train_acc)
train_loss.append(epoch_train_loss)
test_acc.append(epoch_test_acc)
test_loss.append(epoch_test_loss)
template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}')
print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss))
print('Done')
print('best_acc:',best_acc)Epoch: 1, Train_acc:12.2%, Train_loss:2.701, Test_acc:13.9%,Test_loss:2.544
Epoch: 2, Train_acc:20.8%, Train_loss:2.386, Test_acc:20.6%,Test_loss:2.377
Epoch: 3, Train_acc:26.1%, Train_loss:2.228, Test_acc:22.5%,Test_loss:2.274...
Epoch:19, Train_acc:51.6%, Train_loss:1.528, Test_acc:35.8%,Test_loss:1.864
Epoch:20, Train_acc:53.9%, Train_loss:1.499, Test_acc:35.3%,Test_loss:1.852
Done
best_acc: 0.37430555555555556
繼續(xù)訓(xùn)練所有層
for param in model.parameters():
param.requires_grad = True
# 再繼續(xù)訓(xùn)練所有的參數(shù),學(xué)習(xí)率調(diào)小一點(diǎn)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.92)
# 損失函數(shù)
criterion = nn.CrossEntropyLoss()# 加載之前訓(xùn)練好的權(quán)重參數(shù) checkpoint = torch.load(filename) best_acc = checkpoint['best_acc'] model.load_state_dict(checkpoint['state_dict'])
epochs = 20
train_loss = []
train_acc = []
test_loss = []
test_acc = []
best_acc = 0
filename='best_vgg16.pth'
for epoch in range(epochs):
model.train()
epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, optimizer)
scheduler.step()#學(xué)習(xí)率衰減
model.eval()
epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
# 保存最優(yōu)模型
if epoch_test_acc > best_acc:
best_acc = epoch_test_acc
state = {
'state_dict': model.state_dict(),#字典里key就是各層的名字,值就是訓(xùn)練好的權(quán)重
'best_acc': best_acc,
'optimizer' : optimizer.state_dict(),
}
torch.save(state, filename)
train_acc.append(epoch_train_acc)
train_loss.append(epoch_train_loss)
test_acc.append(epoch_test_acc)
test_loss.append(epoch_test_loss)
template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}')
print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss))
print('Done')
print('best_acc:',best_acc)Epoch: 1, Train_acc:41.0%, Train_loss:1.654, Test_acc:57.5%,Test_loss:1.301
Epoch: 2, Train_acc:72.3%, Train_loss:0.781, Test_acc:58.9%,Test_loss:1.139
Epoch: 3, Train_acc:87.0%, Train_loss:0.381, Test_acc:67.8%,Test_loss:1.079
...
Epoch:19, Train_acc:99.3%, Train_loss:0.033, Test_acc:74.2%,Test_loss:0.895
Epoch:20, Train_acc:99.9%, Train_loss:0.003, Test_acc:74.4%,Test_loss:1.001
Done
best_acc: 0.7666666666666667
四、結(jié)果可視化
import matplotlib.pyplot as plt
#隱藏警告
import warnings
warnings.filterwarnings("ignore") #忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標(biāo)簽
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負(fù)號(hào)
plt.rcParams['figure.dpi'] = 100 #分辨率
epochs_range = range(epochs)
plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
到此這篇關(guān)于pytorch實(shí)現(xiàn)好萊塢明星識(shí)別的文章就介紹到這了,更多相關(guān)pytorch實(shí)現(xiàn)好萊塢明星識(shí)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解PyTorch手寫數(shù)字識(shí)別(MNIST數(shù)據(jù)集)
- pytorch cnn 識(shí)別手寫的字實(shí)現(xiàn)自建圖片數(shù)據(jù)
- pytorch實(shí)現(xiàn)圖像識(shí)別(實(shí)戰(zhàn))
- pytorch實(shí)現(xiàn)MNIST手寫體識(shí)別
- 超詳細(xì)PyTorch實(shí)現(xiàn)手寫數(shù)字識(shí)別器的示例代碼
- Pytorch實(shí)現(xiàn)的手寫數(shù)字mnist識(shí)別功能完整示例
- pytorch實(shí)現(xiàn)手寫數(shù)字圖片識(shí)別
- PyTorch一小時(shí)掌握之圖像識(shí)別實(shí)戰(zhàn)篇
相關(guān)文章
python中requests模擬登錄的三種方式(攜帶cookie/session進(jìn)行請求網(wǎng)站)
這篇文章主要介紹了python中requests模擬登錄的三種方式(攜帶cookie/session進(jìn)行請求網(wǎng)站),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
解決PyCharm IDE環(huán)境下,執(zhí)行unittest不生成測試報(bào)告的問題
這篇文章主要介紹了解決PyCharm IDE環(huán)境下,執(zhí)行unittest不生成測試報(bào)告的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Python OpenCV使用dlib進(jìn)行多目標(biāo)跟蹤詳解
這篇文章主要為大家介紹了如何使用 dlib 庫在實(shí)時(shí)視頻中有效地跟蹤多個(gè)對象,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定幫助,需要的可以參考一下2022-03-03
Pandas對每個(gè)分組應(yīng)用apply函數(shù)的實(shí)現(xiàn)
這篇文章主要介紹了Pandas對每個(gè)分組應(yīng)用apply函數(shù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Python入門教程(三十一)Python的Try和Except
這篇文章主要介紹了Python入門教程(三十一)Python的Try Except,當(dāng)我們調(diào)用Python并發(fā)生錯(cuò)誤或異常時(shí),通常會(huì)停止并生成錯(cuò)誤消息,2023-05-05
可以使用try語句處理這些異常,需要的朋友可以參考下
Python通過模塊化開發(fā)優(yōu)化代碼的技巧分享
模塊化開發(fā)就是把代碼拆成一個(gè)個(gè)“零件”,該封裝封裝,該拆分拆分,下面小編就來和大家簡單聊聊python如何用模塊化開發(fā)進(jìn)行代碼優(yōu)化吧2025-04-04

