本課主要2個實踐内容:1、keras中資料集豐富,從資料集中提取更多特征(Data augmentation)
2、遷移學習(Tranform learning)
代碼:https://github.com/jsxyhelu/DateSets
1、keras中資料集豐富,從資料集中提取更多特征(Data augmentation)keras是比較現代化的DL工具,是以這方面的功能都是具備的。這裡首先将相關知識進行整理,然後将例子進行實作,特别注重結果的展示。
具體内容包括:
- 旋轉 | 反射變換(Rotation/reflection): 随機旋轉圖像一定角度; 改變圖像内容的朝向;
- 翻轉變換(flip): 沿着水準或者垂直方向翻轉圖像;
- 縮放變換(zoom): 按照一定的比例放大或者縮小圖像;
- 平移變換(shift): 在圖像平面上對圖像以一定方式進行平移;
- 可以采用随機或人為定義的方式指定平移範圍和平移步長, 沿水準或豎直方向進行平移. 改變圖像内容的位置;
- 尺度變換(scale): 對圖像按照指定的尺度因子, 進行放大或縮小; 或者參照SIFT特征提取思想, 利用指定的尺度因子對圖像濾波構造尺度空間. 改變圖像内容的大小或模糊程度;
- 對比度變換(contrast): 在圖像的HSV顔色空間,改變飽和度S和V亮度分量,保持色調H不變. 對每個像素的S和V分量進行指數運算(指數因子在0.25到4之間), 增加光照變化;
-
噪聲擾動(noise): 對圖像的每個像素RGB進行随機擾動, 常用的噪聲模式是椒鹽噪聲和高斯噪聲;
使用的函數為:

參數非常多,用以生成一個batch的圖像資料,支援實時資料提升。訓練時該函數會無限生成資料,直到達到規定的epoch次數為止;那麼在訓練的時候肯定是需要結合fit_generate來使用,正好是最近研究的。
主要方法:
a、flow(self, X, y, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='png')
将會傳回一個生成器,這個生成器用來擴充資料,每次都會産生batch_size個樣本。
因為目前我們隻導入了一張圖檔,是以每次生成的圖檔都是基于這張圖檔而産生的,可以看到結果,旋轉、位移、放大縮小,統統都有。正如其名稱,這個生成器可以一直生成下去。
b、flow_from_directory(directory):
以檔案夾路徑為參數,生成經過資料提升/歸一化後的資料,在一個無限循環中無限産生batch資料
e.g
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
# 指定參數
# rotation_range 旋轉
# width_shift_range 左右平移
# height_shift_range 上下平移
# zoom_range 随機放大或縮小
img_generator = ImageDataGenerator(
rotation_range = 90,
width_shift_range = 0.2,
height_shift_range = 0.2,
zoom_range = 0.3
)
# 導入并顯示圖檔
img_path = 'e:/template/lena.jpg'
img = image.load_img(img_path)
plt.imshow(img)
plt.show()
# 将圖檔轉為數組
x = image.img_to_array(img)
# 擴充一個次元
x = np.expand_dims(x, axis=0)
# 生成圖檔
gen = img_generator.flow(x, batch_size=1)
# 顯示生成的圖檔
plt.figure()
for i in range(3):
for j in range(3):
x_batch = next(gen)
idx = (3*i) + j
plt.subplot(3, 3, idx+1)
plt.imshow(x_batch[0]/256)
x_batch.shape
代碼中的絕對核心一句
這樣,gen相當于是img_generatror的一個生成器,下面直接使用next(gen)就可以不斷生成。
e.g2驗證DateAugment性能。
都說這個DateAugment好,但是不之際動手實踐一下,總是不放心。
from keras.datasets import cifar10
from keras.layers.core import Dense, Flatten, Activation, Dropout
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.utils import np_utils
from keras.utils import generic_utils
(x_train, y_train),(x_test, y_test) = cifar10.load_data()
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)
def preprocess_data(x):
x /= 255
x -= 0.5
x *= 2
return x
# 預處理
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train = preprocess_data(x_train)
x_test = preprocess_data(x_test)
# one-hot encoding
n_classes = 10
y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)
# 取 20% 的訓練資料
x_train_part = x_train[:10000]
y_train_part = y_train[:10000]
print(x_train_part.shape, y_train_part.shape)
# 建立一個簡單的卷積神經網絡,序貫結構
def build_model():
model = Sequential()
model.add(Conv2D(64, (3,3), input_shape=(32,32,3)))
model.add(Activation('relu'))
model.add(BatchNormalization(scale=False, center=False))
model.add(Conv2D(32, (3,3)))
model.add(MaxPooling2D((2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(256))
model.add(BatchNormalization())
model.add(Dense(n_classes))
model.add(Activation('softmax'))
return model
# 訓練參數
batch_size = 128
#epochs = 20
epochs = 2
#cifar-10 20%資料,訓練結果,繪圖
model = build_model()
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train_part, y_train_part, epochs=epochs, batch_size=batch_size, verbose=1, validation_split=0.1)
loss, acc = model.evaluate(x_test, y_test, batch_size=32)
print('Loss: ', loss)
print('Accuracy: ', acc)
#cifar-10 20%資料 + Data Augmentation.訓練結果
# 設定生成參數
rotation_range = 20,
zoom_range = 0.2
model_2 = build_model()
model_2.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
#采用文檔中提示自動方法
img_generator.fit(x_train_part)
# fits the model_2 on batches with real-time data augmentation:
model_2.fit_generator(img_generator.flow(x_train_part, y_train_part, batch_size=batch_size),
steps_per_epoch=len(x_train_part), epochs=epochs)
初步比較結果:
原始
Loss: 1.6311466661453247
Accuracy: 0.6169
調整
Epoch 1/20
2184/10000 [=====>........................] - ETA: 11:11 - loss: 1.0548 - acc: 0.6254
雖然沒有走完,但是已經初見端倪。
基于前面已經實作的代碼,在fasion_mnist上實作vgg的模型遷移。
from keras.datasets import fashion_mnist
import gc
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.applications.vgg16 import VGG16
from keras.optimizers import SGD
import os
import cv2
import h5py as h5py
def tran_y(y):
y_ohe = np.zeros(10)
y_ohe[y] = 1
return y_ohe
epochs = 1
# 如果硬體配置較高,比如主機具備32GB以上記憶體,GPU具備8GB以上顯存,可以适當增大這個值。VGG要求至少48像素
ishape=48
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
X_train = [cv2.cvtColor(cv2.resize(i, (ishape, ishape)), cv2.COLOR_GRAY2BGR) for i in X_train]
X_train = np.concatenate([arr[np.newaxis] for arr in X_train]).astype('float32')
X_train /= 255.0
X_test = [cv2.cvtColor(cv2.resize(i, (ishape, ishape)), cv2.COLOR_GRAY2BGR) for i in X_test]
X_test = np.concatenate([arr[np.newaxis] for arr in X_test]).astype('float32')
X_test /= 255.0
y_train_ohe = np.array([tran_y(y_train[i]) for i in range(len(y_train))])
y_test_ohe = np.array([tran_y(y_test[i]) for i in range(len(y_test))])
y_train_ohe = y_train_ohe.astype('float32')
y_test_ohe = y_test_ohe.astype('float32')
model_vgg = VGG16(include_top = False, weights = 'imagenet', input_shape = (ishape, ishape, 3))
for layer in model_vgg.layers:
layer.trainable = False
model = Flatten()(model_vgg.output)
model = Dense(4096, activation='relu', name='fc1')(model)
model = Dense(4096, activation='relu', name='fc2')(model)
model = Dropout(0.5)(model)
model = Dense(10, activation = 'softmax', name='prediction')(model)
model_vgg_mnist_pretrain = Model(model_vgg.input, model, name = 'vgg16_pretrain')
model_vgg_mnist_pretrain.summary()
sgd = SGD(lr = 0.05, decay = 1e-5)
model_vgg_mnist_pretrain.compile(loss = 'categorical_crossentropy', optimizer = sgd, metrics = ['accuracy'])
log = model_vgg_mnist_pretrain.fit(X_train, y_train_ohe, validation_data = (X_test, y_test_ohe), epochs = epochs, batch_size = 64)
score = model_vgg_mnist_pretrain.evaluate(X_test, y_test_ohe, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
plt.figure('acc')
plt.subplot(2, 1, 1)
plt.plot(log.history['acc'],'r--',label='Training Accuracy')
plt.plot(log.history['val_acc'],'r-',label='Validation Accuracy')
plt.legend(loc='best')
plt.xlabel('Epochs')
plt.axis([0, epochs, 0.9, 1])
plt.figure('loss')
plt.subplot(2, 1, 2)
plt.plot(log.history['loss'],'b--',label='Training Loss')
plt.plot(log.history['val_loss'],'b-',label='Validation Loss')
plt.axis([0, epochs, 0, 1])
plt.show()
os.system("pause")
其中絕對核心為:
model = Flatten()(model_vgg.output)
model = Dense(10, activation = 'softmax', name='prediction')(model)
遷移學習非常重要(也隻有這裡需要編碼)就是你遷移的那幾層,如何進行修改。可能是要和你實際操作的資料的模式是相關的。
Test loss: 0.10201766314683482
Test accuracy: 0.9673
小結:本課主要2個實踐内容:
1、keras中資料集豐富,從資料集中提取更多特征(Data augmentation)
分别使用了cifar10和fasion_mnist資料集。這兩個資料集能夠很友善地用以實驗,一方面是因為它們都是已經規整好的資料集,另一方面,兩者
都是“單”資料集,也就是一個标簽就是一個圖檔類型的情況。這些都可能被進一步複雜。
來自為知筆記(Wiz)目前方向:圖像拼接融合、圖像識别
聯系方式:[email protected]