[Day 09] 从 tensorflow.keras 开始的 VGG Net 生活 (第二季)

2. VGG 实作(tensorflow)

2.1 南无观世"import"啥?

import itertools
from sklearn.metrics import confusion_matrix, classification_report
from tensorflow.keras.applications import vgg16
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras.utils import to_categorical
import tensorflow as tf
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt

2.2 自定义函数

  1. 读取fer2013.csv用的
def prepare_data(data):
    image_array = np.zeros(shape=(len(data), 48, 48, 1))
    image_label = np.array(list(map(int, data['emotion'])))

    for i, row in enumerate(data.index):
        image = np.fromstring(data.loc[row, 'pixels'], dtype=int, sep=' ')
        image = np.reshape(image, (48, 48, 1))  # 灰阶图的channel数为1
        image_array[i] = image

    return image_array, image_label
  1. 因为VGG预训练模型的输入层需要3通道的图像,所以我直接复制第1通道的阵列到2和3通道上。
def convert_to_3_channels(img_arrays):
    sample_size, nrows, ncols, c = img_arrays.shape
    img_stack_arrays = np.zeros((sample_size, nrows, ncols, 3))
    for _ in range(sample_size):
        img_stack = np.stack(
            [img_arrays[_][:, :, 0], img_arrays[_][:, :, 0], img_arrays[_][:, :, 0]], axis=-1)
        img_stack_arrays[_] = img_stack/255
    return img_stack_arrays
  1. 建立预训练模型,这里第一次执行时会需要下载一段时间
def build_model(preModel=VGG16, num_classes=7):
    pred_model = preModel(include_top=False, weights='imagenet',
                              input_shape=(48, 48, 3),
                              pooling='max', classifier_activation='softmax')
    output_layer = Dense(
        num_classes, activation="softmax", name="output_layer")

    model = tf.keras.Model(
        pred_model.inputs, output_layer(pred_model.output))

    model.compile(optimizer=tf.keras.optimizers.Adam(),
                  loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy'])

    return model

2.3 资料读取与切分训练、验证集

这边要注意的是,我们需要使用to_categorical()将标签(y)转成独热编码(One-hot encoding)。
才能够做分类任务的训练

df_raw = pd.read_csv("D:/mycodes/AIFER/data/fer2013.csv")
# 资料切割(训练、验证、测试)
df_train = df_raw[df_raw['Usage'] == 'Training']
df_val = df_raw[df_raw['Usage'] == 'PublicTest']

X_train, y_train = prepare_data(df_train)
X_val, y_val = prepare_data(df_val)

X_train = convert_to_3_channels(X_train)
X_val = convert_to_3_channels(X_val)

y_train_oh = to_categorical(y_train)
y_val_oh = to_categorical(y_val)

表情范例(angry类别)

表情范例

2.4 测试模型输入与输出是否符合资料格式

如果这边有错误回报,那就要回去检查prepare_data()是否有bug。
这里我们输入第一笔资料进去,
输出维度(1,7)代表有1笔资料,该资料长度为7,
范例: np.array([0.1, 0.2, 0.5, 0.0, 0.1, 0.0, 0.0])
其中每个位置的数字代表此资料属於对应的表情类别的机率。

model_vgg16 = build_model()
prob_vgg16 = model_vgg16(X_train[:1]).numpy()
print(prob_vgg16.shape)

#Output: (1, 7)

2.5 开始训练

因为接下来要对不同模型架构(resnet和mobilenet等等)做大量的实验,
所以我统一制定epochs = 30, batch_size=32,以求公平性的比较。

epochs = 30
batch_size = 32

hist1 = model_vgg16.fit(X_train, y_train_oh, validation_data=(X_val, y_val_oh),
                        epochs=epochs, batch_size=batch_size)

结语

  1. 基本上所有模型都是这样训练的,只是在applications import 不同的模型而已
  2. 因为code基本一样,之後几个模型就不会附上code了,
    所以就会以一篇文章介绍一个演算法的速度前进。
  3. 等到所有模型训练完之後,我再来呈现数据的比较

敬请期待/images/emoticon/emoticon35.gif


<<:  Day9 Let's ODOO: View(2) Structure

>>:  Day-13 线性时间演算法 : Counting sort

风险处置(风险回应)[Risk Treatment (Risk Response)]

-风险处理(风险应对) 无论我们实施哪种加密方案,都可以降低风险。ISO 27005 使用术语“风...

[Day 44] 心情随笔後台及前台(六) - 心情随笔前台画面

接下来我们要做的是心情随笔前台的画面, 我们要在 app/Http/Controllers/Home...

AE-Lightning 雷电云特效3-Day25

接续昨天的练习~ 1.拉入第二个素材(云的图档),这个素材主要便是主要遮挡的的云层 2.Ctrl+D...

Day04:自我增进技术能力与观念的小方法

一、前言   上一篇文章的结尾有提到大家可以在职场上定时自我检视的小习惯,这边分享我自己维持几个月後...

#30-用Tailwind&Gulp做个动态菜单网站(完赛!)

Yo! 因为用Gulp包其他页面,但最後一页临时改成用Tailwind, 在设定上卡了一下...一起...