pytorch 模型微调
生活随笔
收集整理的這篇文章主要介紹了
pytorch 模型微调
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這里面我們使用官方訓練好的resnet50來參加kaggle上面的 dog breed 狗的種類識別來做一個簡單微調實例。
首先我們需要下載官方的數據解壓,只要保持數據的目錄結構即可,這里指定一下目錄的位置,并且看下內容
DATA_ROOT = '/home/huangshaobo/dataset/dog' all_labels_df = pd.read_csv(os.path.join(DATA_ROOT,'labels.csv')) all_labels_df.head()
獲取狗的分類,根據分類進行編號。這里定義了兩個字典,分別以名字和id作為對應,方便后面處理:
添加到列表中:
由于我們的數據集不是官方指定的格式,我們自己定義一個數據集:
我們這里只分割10%的數據作為訓練時的驗證數據:
dataset_names = ['train', 'valid'] stratified_split = StratifiedShuffleSplit(n_splits=1, test_size=0.1, random_state=0) train_split_idx, val_split_idx = next(iter(stratified_split.split(all_labels_df.id, all_labels_df.breed))) train_df = all_labels_df.iloc[train_split_idx].reset_index() val_df = all_labels_df.iloc[val_split_idx].reset_index() print(len(train_df)) print(len(val_df))
使用官方的dataloader載入數據:
定義訓練函數:
def train(model,device, train_loader, epoch):model.train()for batch_idx, data in enumerate(train_loader):x,y= datax=x.to(device)y=y.to(device)optimizer.zero_grad()y_hat= model(x)loss = criterion(y_hat, y)loss.backward()optimizer.step()print ('Train Epoch: {}\t Loss: {:.6f}'.format(epoch,loss.item()))定義測試函數:
def test(model, device, test_loader):model.eval()test_loss = 0correct = 0with torch.no_grad():for i,data in enumerate(test_loader): x,y= datax=x.to(device)y=y.to(device)optimizer.zero_grad()y_hat = model(x)test_loss += criterion(y_hat, y).item() # sum up batch losspred = y_hat.max(1, keepdim=True)[1] # get the index of the max log-probabilitycorrect += pred.eq(y.view_as(pred)).sum().item()test_loss /= len(test_loader.dataset)print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(val_dataset),100. * correct / len(val_dataset)))訓練9次,看看效果:
for epoch in range(1, 10):%time train(model=model_ft,device=DEVICE, train_loader=image_dataloader["train"],epoch=epoch)test(model=model_ft, device=DEVICE, test_loader=image_dataloader["valid"])
我們看到只訓練了9次就達到了80%的準確率,效果還是可以的。
但是每次訓練都需要將一張圖片在全部網絡中進行計算,而且計算的結果每次都是一樣的,這樣浪費了很多計算的資源。 下面我們就將這些不進行反向傳播或者說不更新網絡權重參數層的計算結果保存下來, 這樣我們以后使用的時候就可以直接將這些結果輸入到FC層或者以這些結果構建新的網絡層, 省去了計算的時間,并且這樣如果只訓練全連接層,CPU就可以完成了。
PyTorch論壇中說到可以使用自己手動實現模型中的forward參數,這樣看起來是很簡便的,但是這樣處理起來很麻煩,不建議這樣使用。
這里我們就要采用PyTorch比較高級的API,hook來處理了,我們要先定義一個hook函數
in_list= [] # 這里存放所有的輸出 def hook(module, input, output):#input是一個tuple代表順序代表每一個輸入項,我們這里只有一項,所以直接獲取#需要全部的參數信息可以使用這個打印#for val in input:# print("input val:",val)for i in range(input[0].size(0)):in_list.append(input[0][i].cpu().numpy()) # 在相應的層注冊hook函數,保證函數能夠正常工作,我們這里直接hook 全連接層前面的pool層,獲取pool層的輸入數據,這樣會獲得更多的特征:model_ft.avgpool.register_forward_hook(hook) # 開始獲取輸出,這里我們因為不需要反向傳播,所以直接可以使用no_grad嵌套:%%time with torch.no_grad():for batch_idx, data in enumerate(image_dataloader["train"]):x,y= datax=x.to(DEVICE)y=y.to(DEVICE)y_hat = model_ft(x)總結
以上是生活随笔為你收集整理的pytorch 模型微调的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 页面长度单位,css绝对长度单
- 下一篇: rails kaminari boots