---
# System prepended metadata

title: 深度學習HW2_ Music Scale Recognition by CNN
tags: [pytorch, CNN, Python筆記]

---

# 深度學習HW2_ Music Scale Recognition by CNN 
###### tags: `pytorch`, `Python筆記`, `CNN`

### :small_blue_diamond: 410823001 電機四 許哲瑜


1. what problems you encountered when doing this assignment

    在做本次作業的過程中，發現到不管如何修改模型架構與參數，訓練的準確度都會卡在93%無法繼續增加，仔細看過程式碼之後才發現，我使用 os.listdir()的方式讀取圖片資料夾中的檔案名稱，與 "train_truth.csv" 檔案中的順序並不相同，導致我在訓練時有許多圖片所對應的label是錯誤的!難怪不管怎麼調整模型都不會有更好的成效。

2.	how did you solve the problems?
    
    為了解決上述問題，只需要將該檔案名稱去對應 "train_truth.csv" 中 "filename" 是否相同，利用pandas套件中的loc函式去過濾資料後，再拿取旁邊 "category" 的值即可，實作的程式碼如下:
```python=
label_file = 'train_truth.csv'              # 設定檔案路徑
label = pd.read_csv(label_file)             # 利用 pandas 讀取 csv 檔案 
N = len(label)                              # 取得訓練資料的數量
labels = np.array([0]* N)                   # 建立存放標籤的空陣列
path = os.getcwd() + '\music_train'         # 設定圖片數據的資料夾路徑
class_filenames = os.listdir(path)          # 利用 os.listdir 讀取資料夾中的圖片檔案名稱(type is list)
for i, name in enumerate(class_filenames):
    num = label.loc[label["filename"]==name] # 取得該圖片名稱在 train_truth.csv 中對應的 label值
    labels[i] = int(num['category'])         # 將label值存入上方建立的標籤空陣列中
```


3.	is there any innovative design you've made in this assignment?

    我在訓練模型前有利用 train_test_split 將資料切分成訓練集與驗證集，其中使用stratify 參數設定為label資料，使得切分後的資料集是均勻分布。並且也將每張圖片都做正規化的處理，實作程式碼如下:
```python=
from sklearn.model_selection import train_test_split
# 利用 train_test_split語法 將訓練資料切分成訓練集與測試集: stratify 可以根據給定的標籤數均勻切分、random_state 確保每次重複執行切分的資料都相同
x_train_image, x_test_image, y_train_label, y_test_label = train_test_split(images, labels, stratify = labels, test_size=0.2, random_state=47)
x_train = x_train_image.astype('float32')/255 # 將訓練集圖片數據正規化處理
```
*    另外因為影像分類的問題我之前有使用Tensorflow的框架訓練過，這次選擇用Pytorch來試試看，發現最大的不同是建立訓練模型架構的部分，同樣使用ResNet模型架構，在Tensorflow可以使用遷移式學習得方式，短短幾行程式碼便可以建立好；而Pytorch我是透過老師上課的程式碼一步步建立，雖然過程較為複雜，但也比較了解此模型架構中的各項layer的內容與資料是如何被傳遞的，兩種不同的框架都各有優缺點，使用Tensorflow框架的程式碼如下:
```python=
# Tensorflow的框架 建立 ResNet 模型架構
# 使用遷移式學習的imagenet權重，僅保留「非後全連結層的部分」，即include_top為False，並可使用input_shape指定輸入大小。
import tensorflow.keras.applications as keras_model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
base_model = keras_model.ResNet50(include_top=False, weights="imagenet",
                                input_shape=(H, W, 3), pooling=None, classes=88)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation="relu")(x)
x = Dense(512, activation="relu")(x)
output = Dense(88, activation="softmax")(x)
model = Model(inputs=base_model.input, outputs=output)
model.summary()
```

    
4.	what have you learned in this assignment?
    經過這次讀取檔案與label的教訓，進後會再建立訓練資料時更加小心，確保要輸入訓練模型的資料集是正確的，避免在發生調整各項參數後都沒有效果的慘案發生!


