天天看點

Stanford CS231n實踐筆記(課時22卷積神經網絡工程實踐技巧與注意點 cnn in practise 上)

本課主要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進行随機擾動, 常用的噪聲模式是椒鹽噪聲和高斯噪聲;

    使用的函數為: 

Stanford CS231n實踐筆記(課時22卷積神經網絡工程實踐技巧與注意點 cnn in practise 上)

參數非常多,用以生成一個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

Stanford CS231n實踐筆記(課時22卷積神經網絡工程實踐技巧與注意點 cnn in practise 上)

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]