首先查看keras中的sequential-api:fit 函數
fit(x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0, steps_per_epoch=None, validation_steps=None)x: 訓練數據的 Numpy 數組。 如果模型中的輸入層被命名,你也可以傳遞一個字典,將輸入層名稱映射到 Numpy 數組。 如果從本地框架張量饋送(例如 TensorFlow 數據張量)數據,x 可以是 None(默認)。
y: 目標(標籤)數據的 Numpy 數組。 如果模型中的輸出層被命名,你也可以傳遞一個字典,將輸出層名稱映射到 Numpy 數組。 如果從本地框架張量饋送(例如 TensorFlow 數據張量)數據,y 可以是 None(默認)。
batch_size: 整數或 None。每次梯度更新的樣本數。如果未指定,默認為 32。
epochs: 整數。訓練模型迭代輪次。一個輪次是在整個 x 或 y 上的一輪迭代。請注意,與 initial_epoch 一起,epochs 被理解為 「最終輪次」。模型並不是訓練了 epochs 輪,而是到第 epochs 輪停止訓練。
verbose: 0, 1 或 2。日誌顯示模式。 0 = 安靜模式, 1 = 進度條, 2 = 每輪一行。
callbacks: 一系列的 keras.callbacks.Callback 實例。一系列可以在訓練時使用的回調函數。詳見 callbacks。
validation_split: 在 0 和 1 之間浮動。用作驗證集的訓練數據的比例。模型將分出一部分不會被訓練的驗證數據,並將在每一輪結束時評估這些驗證數據的誤差和任何其他模型指標。驗證數據是清洗之前 x 和y 數據的最後一部分樣本中。
validation_data: 元組 (x_val,y_val) 或元組 (x_val,y_val,val_sample_weights),用來評估損失,以及在每輪結束時的任何模型度量指標。模型將不會在這個數據上進行訓練。這個參數會覆蓋 validation_split。
shuffle: 布爾值(是否在每輪迭代之前混洗數據)或者 字符串 (batch)。batch 是處理 HDF5 數據限制的特殊選項,它對一個 batch 內部的數據進行混洗。當 steps_per_epoch 非 None 時,這個參數無效。
class_weight: 可選的字典,用來映射類索引(整數)到權重(浮點)值,用於加權損失函數(僅在訓練期間)。這可能有助於告訴模型 「更多關注」來自代表性不足的類的樣本。
sample_weight: 訓練樣本的可選 Numpy 權重數組,用於對損失函數進行加權(僅在訓練期間)。您可以傳遞與輸入樣本長度相同的平坦(1D)Numpy 數組(權重和樣本之間的 1:1 映射),或者在時序數據的情況下,可以傳遞尺寸為 (samples, sequence_length) 的 2D 數組,以對每個樣本的每個時間步施加不同的權重。在這種情況下,你應該確保在 compile() 中指定 sample_weight_mode="temporal"。
initial_epoch: 開始訓練的輪次(有助於恢復之前的訓練)。
steps_per_epoch: 在聲明一個輪次完成並開始下一個輪次之前的總步數(樣品批次)。使用 TensorFlow 數據張量等輸入張量進行訓練時,默認值 None 等於數據集中樣本的數量除以 batch 的大小,如果無法確定,則為 1。
validation_steps: 只有在指定了 steps_per_epoch時才有用。停止前要驗證的總步數(批次樣本)。
說明:以固定數量的輪次(數據集上的迭代)訓練模型。
這裡函數是Keras裡的Sequential順序模型,所以本文也是使用的順序模型來進行訓練的。
from keras.models import Sequential上述代碼是導入模型,順序模型是一種多層網絡進行疊加的,所以我們需要創建多個網絡層:輸入層,卷積,池化,全連接等。
輸入層層:Input
卷積層層:conv2d
激活函數:Activation(relu)
池化層:MaxPooling2D
Flatten層:flatten (將多維張量轉為一維的張量,卷積層到全連接層的一個過渡層)
防止過擬合:Dropout
全連接層:Dense
大致我們需要上述幾個函數構建我們的網絡,關於一些概念或者原理的東西,大家可以自行Google,下面是構建網絡的代碼。
inputs = Input(shape = input_shape, name = "inputs")conv1 = Conv2D(32, (3, 3), name = "conv1")(inputs)relu1 = Activation('relu', name="relu1")(conv1)conv2 = Conv2D(32, (3, 3), name = "conv2")(relu1)relu2 = Activation('relu', name="relu2")(conv2)pool2 = MaxPooling2D(pool_size=(2,2), padding='same', name="pool2")(relu2)conv3 = Conv2D(64, (3, 3), name = "conv3")(pool2)relu3 = Activation('relu', name="relu3")(conv3)pool3 = MaxPooling2D(pool_size=(2,2), padding='same', name="pool3")(relu3)x = Flatten()(pool3)x = Dropout(0.25)(x)x = [Dense(len(NUMBER), activation='softmax', name='fc%d'%(i+1))(x) for i in range(4)]outs = Concatenate()(x)有了網絡模型以後還需要編譯一下才能使用。
model = Model(inputs=inputs, outputs=outs)model.compile(optimizer="優化器", loss="損失函數", metrics=['accuracy'])編譯函數第一個參數是優化器,有如下幾個可供選擇:
SGD
RMSprop
Adam
Adadelta
Adagrad
Adamax
Nadam
Ftrl
第二個參數是損失函數,這裡不列出了直接使用binary_crossentropy(交叉熵損失)
tf.keras.losses.BinaryCrossentropy( from_logits=False, label_smoothing=0, reduction="auto", name="binary_crossentropy")第三個參數是推薦參數,默認就好。
有了模型以後還要有數據,數據的格式有兩種
channels_last(以三維為例):(高度, 寬度, 通道)
channels_first(以三維為例):(通道, 高度, 寬度)
這裡通道代表的就是我們的數據集,不過要進行改變成1維。因為我們通道會定義為1。
if K.image_data_format() == 'channels_first': input_shape = (1, width, height) else: input_shape = (width, height, 1)然後我們要將圖片導入並且轉一維。取一維的總長度,緯度是1,寬度,高度,然後重置圖片,這裡使用的是NumPy。
np.reshape(np.shape[0], 1, width, height)這樣我們就有了圖片組,和Keras對應的數據格式(這時候是空的)。還記得網絡層裡的第一層嗎?
inputs = Input(shape = input_shape, name = "inputs")這裡的input_shape就是我們剛才創建的空的Keras圖片格式。這裡為什麼傳入空的,是因為這裡只是當做佔位符,可以理解為初始化了一個類,但是我們並沒有開始執行這個類。
下面就是使用Fit函數進行訓練了,訓練前我們可以使用
進行模型的查看,fit函數訓練寫法
history = model.fit("訓練圖片數據", "訓練圖片標籤", batch_size="訓練一輪使用的樣本數量", epochs="訓練多少輪", verbose=2, validation_data=("測試圖片數據", "測試圖片標籤"), shuffle=True )模型輸出
Model: "model_1"__________________________________________________________________________________________________Layer (type) Output Shape Param # Connected to ==================================================================================================inputs (InputLayer) (None, 37, 100, 1) 0 __________________________________________________________________________________________________conv1 (Conv2D) (None, 35, 98, 32) 320 inputs[0][0] __________________________________________________________________________________________________relu1 (Activation) (None, 35, 98, 32) 0 conv1[0][0] __________________________________________________________________________________________________conv2 (Conv2D) (None, 33, 96, 32) 9248 relu1[0][0] __________________________________________________________________________________________________relu2 (Activation) (None, 33, 96, 32) 0 conv2[0][0] __________________________________________________________________________________________________pool2 (MaxPooling2D) (None, 17, 48, 32) 0 relu2[0][0] __________________________________________________________________________________________________conv3 (Conv2D) (None, 15, 46, 64) 18496 pool2[0][0] __________________________________________________________________________________________________relu3 (Activation) (None, 15, 46, 64) 0 conv3[0][0] __________________________________________________________________________________________________pool3 (MaxPooling2D) (None, 8, 23, 64) 0 relu3[0][0] __________________________________________________________________________________________________flatten_1 (Flatten) (None, 11776) 0 pool3[0][0] __________________________________________________________________________________________________dropout_1 (Dropout) (None, 11776) 0 flatten_1[0][0] __________________________________________________________________________________________________fc1 (Dense) (None, 2) 23554 dropout_1[0][0] __________________________________________________________________________________________________fc2 (Dense) (None, 2) 23554 dropout_1[0][0] __________________________________________________________________________________________________fc3 (Dense) (None, 2) 23554 dropout_1[0][0] __________________________________________________________________________________________________fc4 (Dense) (None, 2) 23554 dropout_1[0][0] __________________________________________________________________________________________________concatenate_1 (Concatenate) (None, 8) 0 fc1[0][0] fc2[0][0] fc3[0][0] fc4[0][0] ==================================================================================================Total params: 122,280Trainable params: 122,280Non-trainable params: 0每一輪的訓練結果
Train on 5000 samples, validate on 1000 samplesEpoch 1/10 - 48s - loss: 0.6951 - accuracy: 0.5081 - val_loss: 0.6918 - val_accuracy: 0.5217Epoch 2/10 - 47s - loss: 0.6865 - accuracy: 0.5583 - val_loss: 0.6696 - val_accuracy: 0.6655Epoch 3/10 - 52s - loss: 0.6014 - accuracy: 0.6966 - val_loss: 0.5228 - val_accuracy: 0.7720Epoch 4/10 - 42s - loss: 0.4662 - accuracy: 0.7880 - val_loss: 0.4102 - val_accuracy: 0.8217Epoch 5/10 - 41s - loss: 0.3911 - accuracy: 0.8293 - val_loss: 0.3460 - val_accuracy: 0.8558Epoch 6/10 - 41s - loss: 0.3280 - accuracy: 0.8625 - val_loss: 0.2909 - val_accuracy: 0.8835Epoch 7/10 - 41s - loss: 0.2785 - accuracy: 0.8886 - val_loss: 0.2580 - val_accuracy: 0.8947Epoch 8/10 - 37s - loss: 0.2477 - accuracy: 0.9034 - val_loss: 0.2297 - val_accuracy: 0.9143Epoch 9/10 - 44s - loss: 0.2293 - accuracy: 0.9099 - val_loss: 0.2136 - val_accuracy: 0.9200Epoch 10/10 - 48s - loss: 0.2167 - accuracy: 0.9155 - val_loss: 0.2115 - val_accuracy: 0.9185loss:訓練數據的損失(每輪減少)
accuracy:訓練數據的精準度(每輪增加)
val_loss:驗證數據的損失(每輪減少)
val_accuracy:驗證數據的精準度(每輪增加)
這裡在第十輪發現驗證數據有點開始過擬合了,還是訓練數據少。所以直接使用第九輪的模型。
上述代碼是保存模型
model = load_model(MODEL_PATH)上述代碼是載入模型,當我們訓練好以後模型保存到本地。下次可以直接載入模型進行識別。
model = load_model(MODEL_PATH)for filename in glob.glob(TESTPATH+'*.png'): image = np.array(Image.open(filename)) pname = model.predict(image) str_code=filename.lstrip(TESTPATH).rstrip('.png') str_code_list = str_code.split("-") name = str_code_list[1] if(name==toText(pname)): ok=ok+1 else: err=err+1print("\033[1;32;43merr:"+str(err)+",ok:"+str(ok)+"\033[0m")上述代碼是識別代碼
Jmeter使用方法可以參照:Jmeter 驗證碼自動識別登錄