深度学习示例(五)
原文:
annas-archive.org/md5/81c037237f3318d7e4e398047d4d8413译者:飞龙
第十六章:实现鱼类识别
以下是《鱼类识别》部分的完整代码,该部分内容涵盖在第一章《数据科学 – 鸟瞰》中。
鱼类识别的代码
在解释了鱼类识别示例的主要构建模块之后,我们准备好将所有代码片段连接在一起,看看我们是如何用仅仅几行代码构建出这样一个复杂的系统的:
#Loading the required libraries along with the deep learning platform Keras with TensorFlow as backend
import numpy as np
np.random.seed(2017)
import os
import glob
import cv2
import pandas as pd
import time
import warnings
from sklearn.cross_validation import KFold
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.optimizers import SGD
from keras.callbacks import EarlyStopping
from keras.utils import np_utils
from sklearn.metrics import log_loss
from keras import __version__ as keras_version
# Parameters
# ----------
# x : type
# Description of parameter `x`.
def rezize_image(img_path):
img = cv2.imread(img_path)
img_resized = cv2.resize(img, (32, 32), cv2.INTER_LINEAR)
return img_resized
#Loading the training samples from their corresponding folder names, where we have a folder for each type
def load_training_samples():
#Variables to hold the training input and output variables
train_input_variables = []
train_input_variables_id = []
train_label = []
# Scanning all images in each folder of a fish type
print('Start Reading Train Images')
folders = ['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT']
for fld in folders:
folder_index = folders.index(fld)
print('Load folder {} (Index: {})'.format(fld, folder_index))
imgs_path = os.path.join('..', 'input', 'train', fld, '*.jpg')
files = glob.glob(imgs_path)
for file in files:
file_base = os.path.basename(file)
# Resize the image
resized_img = rezize_image(file)
# Appending the processed image to the input/output variables of the classifier
train_input_variables.append(resized_img)
train_input_variables_id.append(file_base)
train_label.append(folder_index)
return train_input_variables, train_input_variables_id, train_label
#Loading the testing samples which will be used to testing how well the model was trained
def load_testing_samples():
# Scanning images from the test folder
imgs_path = os.path.join('..', 'input', 'test_stg1', '*.jpg')
files = sorted(glob.glob(imgs_path))
# Variables to hold the testing samples
testing_samples = []
testing_samples_id = []
#Processing the images and appending them to the array that we have
for file in files:
file_base = os.path.basename(file)
# Image resizing
resized_img = rezize_image(file)
testing_samples.append(resized_img)
testing_samples_id.append(file_base)
return testing_samples, testing_samples_id
# formatting the images to fit our model
def format_results_for_types(predictions, test_id, info):
model_results = pd.DataFrame(predictions, columns=['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER',
'SHARK', 'YFT'])
model_results.loc[:, 'image'] = pd.Series(test_id, index=model_results.index)
sub_file = 'testOutput_' + info + '.csv'
model_results.to_csv(sub_file, index=False)
def load_normalize_training_samples():
# Calling the load function in order to load and resize the training samples
training_samples, training_label, training_samples_id = load_training_samples()
# Converting the loaded and resized data into Numpy format
training_samples = np.array(training_samples, dtype=np.uint8)
training_label = np.array(training_label, dtype=np.uint8)
# Reshaping the training samples
training_samples = training_samples.transpose((0, 3, 1, 2))
# Converting the training samples and training labels into float format
training_samples = training_samples.astype('float32')
training_samples = training_samples / 255
training_label = np_utils.to_categorical(training_label, 8)
return training_samples, training_label, training_samples_id
#Loading and normalizing the testing sample to fit into our model
def load_normalize_testing_samples():
# Calling the load function in order to load and resize the testing samples
testing_samples, testing_samples_id = load_testing_samples()
# Converting the loaded and resized data into Numpy format
testing_samples = np.array(testing_samples, dtype=np.uint8)
# Reshaping the testing samples
testing_samples = testing_samples.transpose((0, 3, 1, 2))
# Converting the testing samples into float format
testing_samples = testing_samples.astype('float32')
testing_samples = testing_samples / 255
return testing_samples, testing_samples_id
def merge_several_folds_mean(data, num_folds):
a = np.array(data[0])
for i in range(1, num_folds):
a += np.array(data[i])
a /= num_folds
return a.tolist()
# Create CNN model architecture
def create_cnn_model_arch():
pool_size = 2 # we will use 2x2 pooling throughout
conv_depth_1 = 32 # we will initially have 32 kernels per conv. layer...
conv_depth_2 = 64 # ...switching to 64 after the first pooling layer
kernel_size = 3 # we will use 3x3 kernels throughout
drop_prob = 0.5 # dropout in the FC layer with probability 0.5
hidden_size = 32 # the FC layer will have 512 neurons
num_classes = 8 # there are 8 fish types
# Conv [32] -> Conv [32] -> Pool
cnn_model = Sequential()
cnn_model.add(ZeroPadding2D((1, 1), input_shape=(3, 32, 32), dim_ordering='th'))
cnn_model.add(Convolution2D(conv_depth_1, kernel_size, kernel_size, activation='relu', dim_ordering='th'))
cnn_model.add(ZeroPadding2D((1, 1), dim_ordering='th')
cnn_model.add(Convolution2D(conv_depth_1, kernel_size, kernel_size, activation='relu', dim_ordering='th'))
cnn_model.add(MaxPooling2D(pool_size=(pool_size, pool_size), strides=(2, 2), dim_ordering='th'))
# Conv [64] -> Conv [64] -> Pool
cnn_model.add(ZeroPadding2D((1, 1), dim_ordering='th'))
cnn_model.add(Convolution2D(conv_depth_2, kernel_size, kernel_size, activation='relu', dim_ordering='th'))
cnn_model.add(ZeroPadding2D((1, 1), dim_ordering='th'))
cnn_model.add(Convolution2D(conv_depth_2, kernel_size, kernel_size, activation='relu', dim_ordering='th'))
cnn_model.add(MaxPooling2D(pool_size=(pool_size, pool_size), strides=(2, 2), dim_ordering='th'))
# Now flatten to 1D, apply FC then ReLU (with dropout) and finally softmax(output layer)
cnn_model.add(Flatten())
cnn_model.add(Dense(hidden_size, activation='relu'))
cnn_model.add(Dropout(drop_prob))
cnn_model.add(Dense(hidden_size, activation='relu'))
cnn_model.add(Dropout(drop_prob))
cnn_model.add(Dense(num_classes, activation='softmax'))
# initiating the stochastic gradient descent optimiser
stochastic_gradient_descent = SGD(lr=1e-2, decay=1e-6, momentum=0.9, nesterov=True)
cnn_model.compile(optimizer=stochastic_gradient_descent, # using the stochastic gradient descent optimiser
loss='categorical_crossentropy') # using the cross-entropy loss function
return cnn_model
#Model using with kfold cross validation as a validation method
def create_model_with_kfold_cross_validation(nfolds=10):
batch_size = 16 # in each iteration, we consider 32 training examples at once
num_epochs = 30 # we iterate 200 times over the entire training set
random_state = 51 # control the randomness for reproducibility of the results on the same platform
# Loading and normalizing the training samples prior to feeding it to the created CNN model
training_samples, training_samples_target, training_samples_id = load_normalize_training_samples()
yfull_train = dict()
# Providing Training/Testing indices to split data in the training samples
# which is splitting data into 10 consecutive folds with shuffling
kf = KFold(len(train_id), n_folds=nfolds, shuffle=True, random_state=random_state)
fold_number = 0 # Initial value for fold number
sum_score = 0 # overall score (will be incremented at each iteration)
trained_models = [] # storing the modeling of each iteration over the folds
# Getting the training/testing samples based on the generated training/testing indices by Kfold
for train_index, test_index in kf:
cnn_model = create_cnn_model_arch()
training_samples_X = training_samples[train_index] # Getting the training input variables
training_samples_Y = training_samples_target[train_index] # Getting the training output/label variable
validation_samples_X = training_samples[test_index] # Getting the validation input variables
validation_samples_Y = training_samples_target[test_index] # Getting the validation output/label variabl
fold_number += 1
print('Fold number {} out of {}'.format(fold_number, nfolds))
callbacks = [
EarlyStopping(monitor='val_loss', patience=3, verbose=0),
]
# Fitting the CNN model giving the defined settings
cnn_model.fit(training_samples_X, training_samples_Y, batch_size=batch_size,
nb_epoch=num_epochs,
shuffle=True, verbose=2, validation_data=(validation_samples_X,
validation_samples_Y),
callbacks=callbacks)
# measuring the generalization ability of the trained model based on the validation set
predictions_of_validation_samples =
cnn_model.predict(validation_samples_X.astype('float32'), batch_size=batch_size,
verbose=2)
current_model_score = log_loss(Y_valid, predictions_of_validation_samples)
print('Current model score log_loss: ', current_model_score)
sum_score += current_model_score*len(test_index)
# Store valid predictions
for i in range(len(test_index)):
yfull_train[test_index[i]] = predictions_of_validation_samples[i]
# Store the trained model
trained_models.append(cnn_model)
# incrementing the sum_score value by the current model calculated score
overall_score = sum_score/len(training_samples)
print("Log_loss train independent avg: ", overall_score)
#Reporting the model loss at this stage
overall_settings_output_string = 'loss_' + str(overall_score) + '_folds_' + str(nfolds) + '_ep_' + str(num_epochs)
return overall_settings_output_string, trained_models
#Testing how well the model is trained
def test_generality_crossValidation_over_test_set(overall_settings_output_string, cnn_models):
batch_size = 16 # in each iteration, we consider 32 training examples at once
fold_number = 0 # fold iterator
number_of_folds = len(cnn_models) # Creating number of folds based on the value used in the training step
yfull_test = [] # variable to hold overall predictions for the test set
#executing the actual cross validation test process over the test set
for j in range(number_of_folds):
model = cnn_models[j]
fold_number += 1
print('Fold number {} out of {}'.format(fold_number, number_of_folds))
#Loading and normalizing testing samples
testing_samples, testing_samples_id = load_normalize_testing_samples()
#Calling the current model over the current test fold
test_prediction = model.predict(testing_samples, batch_size=batch_size, verbose=2)
yfull_test.append(test_prediction)
test_result = merge_several_folds_mean(yfull_test, number_of_folds)
overall_settings_output_string = 'loss_' + overall_settings_output_string \
+ '_folds_' + str(number_of_folds)
format_results_for_types(test_result, testing_samples_id, overall_settings_output_string)
# Start the model training and testing
if __name__ == '__main__':
info_string, models = create_model_with_kfold_cross_validation()
test_generality_crossValidation_over_test_set(info_string, models)