1. 程式人生 > >深度學習例項一——手勢數字識別(tensorflow&pytorch)

深度學習例項一——手勢數字識別(tensorflow&pytorch)

這是吳恩達老師深度學習工程師(網上有資源,大家可以去看看吳老師的課程,還是很有收穫。),第二次課第三週的課後例項作業,可以作為初學者練手的好專案。原專案是tensorflow寫的,我又用pytorch寫了一遍。資料檔案和完整程式碼都傳到github上了。詳情見:https://github.com/idotc/Gesture-digit-recognition

一、Problem statement: SIGNS Dataset

設計一個神經網路用來識別如下圖片手勢中的數字。
在這裡插入圖片描述

  • Training set: 1080 pictures (64 by 64 pixels) of signs representing numbers from 0 to 5 (180 pictures per number).
  • Test set: 120 pictures (64 by 64 pixels) of signs representing numbers from 0 to 5 (20 pictures per number).

二、實現過程

整個過程分為:資料讀取與處理,神經網路的設計,訓練,評測

  1. 資料讀取與處理,這個主要是處理,訓練圖片需要轉化成一維向量,還要把整個訓練集shuffle成一個個mini_batch。對於label,需要轉化成one_hot向量。
  2. 神經網路的設計,網路的設計影響到最後的結果,這個跟經驗有很大的關係,需要多看論文,多實踐。
  3. 訓練,選擇一個好的optimizer 優化器往往能事半功倍
  4. 評測,把訓練和驗證的結果loss,acc.等打印出來,及時調整策略。

三、學習過程和坑

1、np.random.seed(seed)
每次執行程式碼時設定相同的seed,則每次生成的隨機數也相同,如果不設定seed,則每次生成的隨機數都會不一樣。

2、np.random.permutation(m)和np.random.shuffle(m)的區別
假設m是一個數,permutation函式都是生成一個0到m-1的亂序陣列,並返回該陣列。若m是一個數組,區別是shuffle是直接改變傳入m的順序,無返回值;permutation是不改變傳入m的順序,返回一個新的打亂順序的陣列。

permutation = list(np.random.permutation(m))
shuffled_X = X[:, permutation]

3、math.floor(m)
返回一個小於或等於m的最大整數,用於mini_batch劃分陣列中,得到的結果不是整數時,向下取整使用。

batches = math.floor(m/mini_batch_size)

4、a = (c, d)
a為python裡的元組,若為普通的一個元素時,不可以修改,為list物件時候,可以修改其中的值。

mini_batch = (mini_batch_X, mini_batch_Y)

5、one_hot函式

Y = np.eye(C)[Y.reshape(-1)].T

np.eye(C),生成一個列數為C的單位矩陣,np.eye(C)[m],在m處為1的一維向量,即轉化成one_hot向量。

6、損失函式
pytorch裡面提供了一個實現 torch.nn.CrossEntropyLoss(This criterion combines nn.LogSoftmax() and nn.NLLLoss() in one single class),其整合了上面的步驟。這和tensorflow中的tf.nn.softmax_cross_entropy_with_logits函式的功能是一致的。必須明確一點:在pytorch中若模型使用CrossEntropyLoss這個loss函式,則不應該在最後一層再使用softmax進行啟用。
`
7、torch.max(input, dim, keepdim=False, out=None)
這個用作最後的評測。torch.max)(a,0) 返回每一列中最大值的那個元素,且返回索引(返回最大元素在這一列的行索引);torch.max(a,1) 返回每一行中最大值的那個元素,且返回其索引(返回最大元素在這一行的列索引)。troch.max()[1], 只返回最大值的每個索引。torch.max()[1].data 只返回variable中的資料部分。torch.max(test_output, 1)[1].data.squeeze()序列化後用作比較結果。

BUGS:
1、RuntimeError: Variable data has to be a tensor, but got numpy.ndarray
需要將numpy矩陣轉換為Tensor張量:

tensor_data = torch.from_numpy(numpy_data)   		#numpy_data為numpy型別

將Tensor張量轉化為numpy矩陣

numpy_data = tensor_data.numpy()             #tensor_data為tensor張量

2、Pytorch出現 raise NotImplementedError
網路沒定義正確:def forword(self, x):
->def forward(self, x):

3、Expected object of type torch.LongTensor but found type torch.FloatTensor pytorch
在使用CrossEntropyLoss時,常會出現如題的錯誤。錯誤指出,要用longtensor而不是floattensor,於是

per_label = per_label.long()
outputs = outputs.long()

將神經網路輸出和目標label都轉換為longtensor,發現又會出現新問題。
如果是這種情況,我們應該檢查輸入的標籤是0,1格式的,還是0-(C-1)這種格式的,CrossEntropyLoss只適用於0-(c-1)這種格式,如果標籤設定為(0,1)格式,請用MultiLabelSoftMarginLoss,即

criterion = nn.MultiLabelSoftMarginLoss()

發現問題解決。(這個大兄弟解決的:https://blog.csdn.net/u012759006/article/details/82559334)

最後附上一張訓練圖:
在這裡插入圖片描述