# ML2021Spring-hw3 解題筆記
## 題目說明
Modified Food-11 Dataset
128x128 食物圖片,可被分成 11 類
labeled data 只有 3080 張,unlabeled 有 6786 張
Validation 660 labeled data、Testing 3347 images
## 成果(未達標)

過 Medium baseline,但距離 Strong baseline 還有很長一段距離
原始碼:[Github](https://github.com/yzu1103309/ml2021spring-hw3)
## 做了什麼?
### Network
嘗試過 ResNet18,但規定不能使用 Pre-trained Weights
效果沒有到特別突出(有偷偷嘗試了一下 Pre-trained,效果很好,但不行用)
所以最後還是使用自己定義的 Network 為主:
```python=
class Classifier(nn.Module):
def __init__(self):
super(Classifier, self).__init__()
# The arguments for commonly used modules:
# torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)
# torch.nn.MaxPool2d(kernel_size, stride, padding)
# input image size: [3, 128, 128]
self.cnn_layers = nn.Sequential(
nn.Conv2d(3, 128, 5, 1),
nn.BatchNorm2d(128),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0),
nn.Conv2d(128, 256, 3, 1),
nn.BatchNorm2d(256),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0),
nn.Conv2d(256, 512, 3, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0),
nn.Conv2d(512, 512, 3, 1),
nn.BatchNorm2d(512),
nn.ReLU(),
nn.MaxPool2d(2, 2, 0),
)
self.fc_layers = nn.Sequential(
nn.Linear(512 * 6 * 6, 512),
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Linear(512, 256),
nn.BatchNorm1d(256),
nn.ReLU(),
nn.Linear(256, 64),
nn.BatchNorm1d(64),
nn.ReLU(),
nn.Linear(64, 11)
)
def forward(self, x):
x = self.cnn_layers(x)
x = x.flatten(1)
x = self.fc_layers(x)
return x
```
### 訓練設定
* 嘗試 Train 了 200 epoch 左右,但 Accuracy 上升到 60% 左右就很難再提高
* 有加入 Data Augmentation(詳見:[Data Augmentation](#Data-Augmentation))
* 有加入 semi-supervised learning,並設定一些觸發條件(詳見:[Semi-Supervised](#Semi-Supervised))
* batch size 設定 150,但影響不大(只要確保 Ram 不要被塞爆就好)
* 在 Valid Accuracy 最高時將 Model 儲存,最後用最好的進行 predict
### Data Augmentation
```pyhton=
train_tfm = transforms.Compose([
# Resize the image into a fixed shape (height = width = 128)
transforms.Resize((128, 128)),
# You may add some transforms here.
# ToTensor() should be the last one of the transforms.
# transforms.RandomPosterize(bits=2, p=0.5),
transforms.RandomAutocontrast(p=0.5),
transforms.RandomRotation(degrees=(0, 90)),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomPerspective(distortion_scale=0.3, p=0.5),
transforms.ToTensor(),
])
```
選定以上幾種增強方式,包括調整對比度、旋轉 0~90 度,水平翻轉、隨機視角
在使用 semi-supervised 之前,可以讓 Accuracy 上升
也試過其他的 Augmentation 組合,但結果的差距不大
### Semi-Supervised
經過測試,因為 Labeled Data 真的太少,很容易 Overfit,所以加入 Semi-supervised
但是如果在 Model 很不穩定時直接開始做 Semi-supervised,反而造成反效果
所以先加入一些限制:
* 當 Valid Accuracy 大於 0.55 時,下一個 iteration 用此 Model 進行 Labeling
* Labeling 時,信心值要 > 0.8 才進行 Label
但此時發現,雖然可以使 Accuracy 升高,不過後面重複循環於 Labeling 和 Training,除了速度很慢之外,Accuracy 也無法有所突破
於是修改了一些機制:
* 當 Valid Accuracy 大於目前 Best Accuracy 、並且大於 0.55 時,將此 Model 儲存
* 下一個 Iteration 用此 Best Model 進行 Labeling
* Labeling 時,信心值要 > 0.8 才進行 Label
但是,Model 進步到一定程度,沒辦法再超過 Best Accuracy,就無法再 Label 新的 Data,Training 停滯
最後將限制改為以下設置:
* 當 Valid Accuracy 大於域值(預設:0.5),下一個 iteration 用此 Model 進行 Labeling
* 每一次域值提高一點點(0.1 或 0.2)
* Labeling 時,信心值要 > 0.9 才進行 Label
但還是一樣沒有找到突破點