iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0
AI & Data

PyTorch 生態鏈實戰運用系列 第 7

[Day07] Model Training with PyTorch

  • 分享至 

  • xImage
  •  

前言

本日將利用前一篇建立好的模型,結合先前的資料前處理,利用基礎的PyTorch語法,進行模型的訓練。

資料讀取

根據先前的文章,我們可以藉由以下語法,得到Pytorch的Data Loader:

# prepare dataset
df = pd.read_csv('data/dataset.csv')
datasets = {split : df[df['split'] == split].to_dict('records') for split in SPLITS}

transforms = preprocess.prepare_transform()

processed_datasets = {
    split : monai.data.Dataset(data = datasets[split], transform = transforms)    
    for split in SPLITS
}
data_generators = {
    split : torch.utils.data.DataLoader(processed_datasets[split],
                                        batch_size = BATCH_SIZE,
                                        shuffle = True,
                                        collate_fn = monai.data.utils.pad_list_data_collate,
                                        pin_memory=torch.cuda.is_available())
    for split in SPLITS
}

但從前一篇當中,我們預計模型的輸出會是14維的一個向量,因此會需要把每個label全部Concat起來。對應到transforms,就必須先做以下的修改,而當中的labels就會是我們想要預測的14個症狀的Ground Truth:

LABEL_LIST = ['atelectasis', 'cardiomegaly', 'effusion', 'infiltration', 'mass', 'nodule', 'pneumonia', 'pneumothorax', 'consolidation', 'edema', 'emphysema', 'fibrosis', 'pleural', 'hernia']

transforms = [
        monai.transforms.LoadImageD(keys = ['img']),
        monai.transforms.EnsureChannelFirstD(keys = ['img']),
        monai.transforms.ScaleIntensityD(keys = ['img']),
        monai.transforms.ToTensorD(keys = ['img'] + LABEL_LIST), # 把label們也轉換成tensor
        monai.transforms.AddChanneld(keys = LABEL_LIST), # 整理他們的維度
        monai.transforms.ConcatItemsd(keys = LABEL_LIST, name = 'labels'), # 將整理後維度後的label進行疊合
    ]

接著進行抽樣就可以得到:

>>> for batch in data_generators['TEST']:
>>>     break;
>>> batch['labels'].shape
(256, 14)

損失函數(LOSS FUNCTION)與優化器(optimizer)

由於我們針對14個症狀,每一個類別都是二元分類問題,因此我這裡採用Torch中的BCEWithLogitsLoss作為Loss Function。

這裡做一下簡介,主要是由Binary Cross Entropy (基本上,其實也等同是Binomial Distribution的log-likelihood函數,不過差個負號跟常數倍)

Sigmoid Function (大多時候,在統計內也稱為Logistic Function)

所組成。

比起先對model的結果取Sigmoid再算BCE,放在一起的好處主要是有數值計算上的好處。(試想,分開等於先取exponetial再取log ...)另外,除了資料以外,損失函數幾乎是整個機械學習領域水最深的一塊,因此這邊就不再多做什麼贅述。

另外,optimizer的部份則選用常見於實驗中的Adam,好處是收斂快速,不過實務上有一些研究表示Generalization error比起其他慢的會差一些就是。

結合在一起也很容易,輸入以下即可:

loss_function = torch.nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(model.parameters(), 1e-3)

訓練模型

建立好以上以後,就可以利用PyTorch透過反向傳播法(back-propogation)對模型進行訓練,參考語法如下:

inputs, labels = batch['img'].to(device), batch['labels'].float().to(device)
optimizer.zero_grad() # 初始化這次傳播的梯度
outputs = model(inputs) # 進行forward propogation
loss = loss_function(outputs, labels) # 計算當前的loss
loss.backward() # 利用loss計算梯度
optimizer.step() # 利用這次算出來的梯度,對模型的weights進行更新

實作

一樣本次的實作有放在Github內,簡單執行就可以得到結果:

# python src/train.py
----------
epoch 1/1
1/515, train_loss: 1.8068
2/515, train_loss: 1.6626
3/515, train_loss: 1.5855
4/515, train_loss: 1.4236
5/515, train_loss: 1.4121
6/515, train_loss: 1.3223
7/515, train_loss: 1.2272
8/515, train_loss: 1.1468
9/515, train_loss: 1.0351
10/515, train_loss: 1.0378

簡單執行了10個step。很好,loss有在穩定下降,這代表模型是有在訓練集當中學習到東西的!

本日小節

  • 調整一下先前的transforms 來符合模型的設計
  • 挑選loss以及optimizer來使用
  • 初步進行訓練,得到了loss可以下降的結果

上一篇
[Day06] Design a Model
下一篇
[Day08] Model Validation with PyTorch
系列文
PyTorch 生態鏈實戰運用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言