iT邦幫忙

1

不好意思想請教一下我想要做一個手寫注音的辨識系統,但是收集到足夠的照片之後,我要怎麼去把它分成測試集跟訓練集然後進一步去做訓練?我原本想說可以用keras做好的,但我發現他沒有想說能不能自己來訓練。

ps抱歉剛接觸影像辨識這塊,如果有描述不清楚的地方請見諒

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

3
貓虎皮
iT邦新手 3 級 ‧ 2023-04-09 22:39:25
最佳解答

以下直接給程式碼,因改自舊專案所以有一些殘留(多餘)的東西,請見諒!

架構

projectDir
 - main.py
 - test.py
 - model
 - data
     - 12549
         - 0.jpg
         - ...
     - ...
     - 12582
         - 0.jpg
         - ...

main.py

tags = [chr(i) for i in range(ord('ㄅ'), ord('ㄦ')+1)]
INPUT_SIZE = 128*128*1
OUTPUT_SIZE = len(tags)
HIDDEN_LAYER_LENGTH = 10
HIDDEN_SIZE = 50
TEST_DATA_QUANTITY = 1
LEARNING_RATE = 0.00001

import os
import numpy as np
import tensorflow as tf

from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras import Sequential
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam

import cv2

def createModel():
    model = Sequential()
    model.add(Dense(500, Activation('relu'), input_dim = INPUT_SIZE))
    for _ in range(HIDDEN_LAYER_LENGTH):
        model.add(Dense(HIDDEN_SIZE))
    model.add(Dense(OUTPUT_SIZE, Activation('softmax')))
    return model

model = createModel()
model.summary()

def train(trainData, debug:bool = False):
    [x_train, y_train, x_test, y_test, tags] = [trainData['x_train'], trainData['y_train'], trainData['x_test'], trainData['y_test'], trainData['tags']]
    x_train = np.array(x_train).astype(np.float32)
    x_test = np.array(x_test).astype(np.float32)
    y_train = np.array(y_train)
    y_train_one_hot = []
    y_test_one_hot = []
    for y in y_train:
        one_hot = [0 for _ in range(len(tags))]
        one_hot[tags.index(y)] = 1
        y_train_one_hot.append(one_hot)
    y_train_one_hot = np.array(y_train_one_hot).astype(np.float32)
    for y in y_test:
        one_hot = [0 for _ in range(len(tags))]
        one_hot[tags.index(y)] = 1
        y_test_one_hot.append(one_hot)
    y_test_one_hot = np.array(y_test_one_hot).astype(np.float32)

    optim = Adam(learning_rate = LEARNING_RATE)
    model.compile(loss='categorical_crossentropy',
                optimizer=optim,
                metrics=['acc'])
    history = model.fit(x_train, y_train_one_hot,
                        batch_size=100,
                        epochs=25,
                        verbose=1,
                        shuffle=True,
                        validation_split=0.1)

    history_dict = history.history
    history_dict.keys()

    if debug:
        import matplotlib.pyplot as plt

        acc = history_dict['acc']
        val_acc = history_dict['val_acc']
        loss = history_dict['loss']
        val_loss = history_dict['val_loss']
        epochs_ = range(1,len(acc)+1)

        plt.plot(epochs_ , loss , label = 'training loss')
        plt.plot(epochs_ , val_loss , label = 'val los')
        plt.title('training and val loss')
        plt.xlabel('epochs')
        plt.ylabel('loss')
        plt.legend()
        plt.show()

        plt.clf()
        plt.plot(epochs_ , acc , label='train accuracy')
        plt.plot(epochs_ , val_acc , label = 'val accuracy')
        plt.title('train and val acc')
        plt.xlabel('epochs')
        plt.ylabel('acc')
        plt.legend()
        plt.show()
        pred = np.argmax(model.predict(x_test), axis=1)
        print([tags[i] for i in pred])

    return(model)

def method(tags, model):
    def predict(*pathList):
        x_test = []
        for path in pathList:
            img = cv2.imread(path)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            img = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)
            x_test.append(np.reshape(img, [128*128*1])/255)
        x_test = np.array(x_test).astype(np.float32)
        pred = np.argmax(model.predict(x_test), axis=1)
        return([tags[i] for i in pred])
    return({
        'predict': predict, 
    })

checkpoint_path = './model/cp-{epoch:04d}.ckpt'
if os.path.isfile(checkpoint_path.format(epoch=0) + '.index'):
    model.load_weights(checkpoint_path.format(epoch=0))
if __name__ == '__main__':
    dataDir = './data'
    tagDirList = os.listdir(dataDir)
    x_train = []
    y_train = []
    for tagDir in tagDirList:
        for imgPath in os.listdir(f'{dataDir}/{tagDir}'):
            img = cv2.imread(f'{dataDir}/{tagDir}/{imgPath}')
            img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            img = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)
            x_train.append(np.reshape(img, [128*128*1])/255)
            y_train.append(chr(int(tagDir)))
    trainData = {
        'x_train': x_train[:-TEST_DATA_QUANTITY], 
        'y_train': y_train[:-TEST_DATA_QUANTITY], 
        'x_test': x_train[-TEST_DATA_QUANTITY:], 
        'y_test': y_train[-TEST_DATA_QUANTITY:], 
        'tags': tags
    }
    # train(trainData)
    train(trainData, True)
    model.save_weights(checkpoint_path.format(epoch=0))
modelMethod = method(tags, model)

test.py

from main import modelMethod
res = modelMethod['predict']('./data/12549/0.jpg')
print(res)

如果要訓練時,可以在projectDir下執行main.py
而如果是要使用模型的話,可以在其他支pyimport該main.py

data下的資料夾之所以用數字是因為cv2在預設情況下,只能讀英文和數字的路徑,
其中12549代表12550代表,以此類推。

希望有幫助到您=^w^=

看更多先前的回應...收起先前的回應...

真的感謝您....我再來研究一下!!!!

不好意思想問一下那我data下的照片是要分別建立好ㄅㄆㄇ分別的資料夾,然後再去做訓練嗎~?

貓虎皮 iT邦新手 3 級 ‧ 2023-04-11 21:22:19 檢舉

對,我是想說使用資料夾來分類,比用檔名或額外的文字檔註明來的方便。
所以你將所有ㄅ的圖片放至data/12549/底下,
ㄆ的圖片放至data/12550/底下,
...
...
再執行(訓練)即可。

希望有幫助到您 =^w^=

https://ithelp.ithome.com.tw/upload/images/20230411/20156378E0dvN4Pljg.png

不好意思後來我出現這個錯誤,不太理解是哪部分有問題。 我ㄅ到ㄦ都有放圖片了

貓虎皮 iT邦新手 3 級 ‧ 2023-04-11 22:14:02 檢舉

第一行的範圍我寫錯了,應該把ㄦ改成ㄩ(因為是「聲母」接著「韻母」接著「介符」)

修改後的第一行:

tags = [chr(i) for i in range(ord('ㄅ'), ord('ㄩ')+1)]

希望有幫助到您=^w^=

謝謝您有成功!!!!那再問一下您注音的照片分別是收集了幾張?
我看網路上資料都是用幾萬張去做訓練自己不知道是怎麼去用那麼多。
我一開始丟的圖片是用小畫家先把尺寸改成28*28然後再畫,再丟到資料夾是可以的嗎~?

貓虎皮 iT邦新手 3 級 ‧ 2023-04-12 07:02:10 檢舉

第99行的地方有寫resize

img = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)

所以不管輸入的圖片多大多小都會在丟進模型訓練之前被拉伸成128x128,至於你要製作多大的圖片data,就得由你自己決定了。

至於圖片的數量,基本上就看你想要怎樣的精確度與訓練時間,沒有一定的規定,只是如果類別較多的話(比如說全部注音都要辨識),那麼資料圖片當然是多一些比較好。

希望有幫助到您 =^w^=

不好意思那我要先特別先去背嗎~?

不好意思那我要先特別先去背嗎~?

還是直接丟進去就好

貓虎皮 iT邦新手 3 級 ‧ 2023-04-12 21:29:38 檢舉

直接丟,不用去背。

但要注意的是,如果你的訓練圖片是淺色底深色字,那麼之後的預測圖片也得給他淺色底深色字(反之亦然)。

如果之後要給他的預測圖片之背景與文字關係與訓練圖片相異,需在進行預測前,先做色彩反轉。

色彩反轉:

# img = cv2.imread('test.png')
img[:, :, :] = 255 - img[:, :, :]
# cv2.imwrite('test.png', img)

希望有幫助到您=^w^=

了解了非常感謝你的指導!!!

不好意思我訓練好模型後要在其他py檔座使用的時候出現這個錯誤會是哪方面參數設定錯誤呢
ValueError: Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 16384), found shape=(None, 28, 28)

貓虎皮 iT邦新手 3 級 ‧ 2023-04-15 18:20:52 檢舉

請提供您出錯時的程式碼片段,以便理解您送入的參數出了什麼問題,感謝。

而單以錯誤訊息來看的話就是reshape沒做,直接送入模型做預測所導致。

希望有幫助到您=^w^=

這段https://ithelp.ithome.com.tw/upload/images/20230415/20156378Ryx4eF2kIH.png

貓虎皮 iT邦新手 3 級 ‧ 2023-04-15 20:24:15 檢舉

你可以比較你寫的跟我給的main.py > method > predict
reshape在這裡更該要做多維資料的扁平化,所以應改成:

# 未經測試
img = np.array(img)
img = img.astype('float32')/255
img = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)
prediction = model.predict([np.reshape(img, [128*128*1])])[0]
prediction = np.argmax(prediction)

比較建議將原先main.py > method > predict直接改成:

def predict(*pathList):
    x_test = []
    for path in pathList:
        img = False
        if type(path) == str:
            img = cv2.imread(path)
        else:
            img = path
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        img = cv2.resize(img, (128, 128), interpolation=cv2.INTER_AREA)
        x_test.append(np.reshape(img, [128*128*1])/255)
    x_test = np.array(x_test).astype(np.float32)
    pred = np.argmax(model.predict(x_test), axis=1)
    return([tags[i] for i in pred])

而在檔案中便可直接將bgr img傳入predict,像這樣:

from main import modelMethod
# res = modelMethod['predict']('./data/12549/0.jpg')
import cv2
img = cv2.imread('./data/12549/0.jpg')
res = modelMethod['predict'](img)
print(res)

希望有幫助到您=^w^=

不好意思我test.py改完之後變成出現這個錯誤
ValueError: Received incompatible tensor with shape (37,) when attempting to restore variable with shape (34,) and name layer_with_weights-11/bias/.ATTRIBUTES/VARIABLE_VALUE.
WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use status.expect_partial(). See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function.
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._iterations
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._learning_rate
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.1
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.2
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.3
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.4
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.5
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.6
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.7
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.8
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.9
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.10
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.11
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.12
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.13
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.14
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.15
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.16
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.17
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.18
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.19
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.20
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.21
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.22
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.23
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.24
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.25
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.26
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.27
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.28
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.29
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.30
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.31
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.32
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.33
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.34
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.35
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.36
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.37
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.38
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.39
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.40
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.41
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.42
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.43
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.44
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.45
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.46
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.47
WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.48

貓虎皮 iT邦新手 3 級 ‧ 2023-04-15 21:17:25 檢舉

如果遇到這種參數不符的錯誤最簡單的方式就是把model資料夾下的檔案皆刪除,然後重新訓練模型(重跑main.py)。

希望有幫助到您=^w^=

不好意思我重新訓練還是一樣

貓虎皮 iT邦新手 3 級 ‧ 2023-04-15 21:50:52 檢舉

你的model檔案有刪掉嗎?如果已經刪了,重新訓練後還是這樣,那我就不清楚了。

了解非常感謝你,我再來試試!

不好意思我發現把model刪掉先執行test.py是可以執行
但是訓練出model之後就不能執行這是正確的嗎?!

貓虎皮 iT邦新手 3 級 ‧ 2023-04-16 09:25:08 檢舉

我不知道您現在的code到底長什麼樣子,所以直接把完整版丟在github(link),您可以將其下載,替換data資料夾成你原來的手寫圖片data後,執行看看。

如果還是出問題,那就真的無法幫忙了,因為在我目前的環境下是可以正確執行的。

希望有幫助到您=^w^=

不好意思我訓練完模型執行test.py後這樣是對的嗎~?!
https://ithelp.ithome.com.tw/upload/images/20230416/20156378GFpkPHTQ9w.png

貓虎皮 iT邦新手 3 級 ‧ 2023-04-16 22:00:32 檢舉

是正確的!

順便補充modelMethod['predict']是一個function,你可以傳入一個或多個圖片參數(bgr圖片陣列圖片路徑),它會返回一個陣列包著你傳入之參數的預測結果。

希望有幫助到您=^w^=

了解~~~
也就是說test.py是看我訓練好的模型能不能啟動嗎~?

貓虎皮 iT邦新手 3 級 ‧ 2023-04-17 22:56:07 檢舉

test.py是給你一段範例的code,告訴你如何引用mian.py並使用其modelMethod['predict']

了解了非常感謝您!!

我要發表回答

立即登入回答