关于这个比赛的介绍可以参考之前一篇文章,本节主要介绍的是模型部分。因为比赛比较冲忙只能测试InceptionResNetV2和DenseNet201的效果。比赛有点遗憾的是没有把所有的单独模型都尝试一边,比较一下效果,第二使用融合模型的时候效果不好,但是没有时间检查,第三没有尝试使用lgb或者catboost对得到的图像特征进行分类。
方案一: 使用InceptionResNetV2()在imagenet预训练好的权重,全连接层使用大小为1024和 1神经元进行分类。
import os
import numpy as np
from keras.applications import InceptionResNetV2, DenseNet201
from keras import regularizers
import keras
from sklearn.model_selection import train_test_split
from keras.models import Model
from keras.preprocessing import image
import warnings
warnings.filterwarnings('ignore')
train_no_rec_path = '../A_model/my_all_train/00'
no_rec_path_list = os.listdir(train_no_rec_path)
len_no_rec = len(no_rec_path_list)
print('len_no_rec:', len_no_rec)
train_rec_path = '../A_model/my_all_train/10'
rec_path_list = os.listdir(train_rec_path)
len_rec = len(rec_path_list)
print('len_rec:', len_rec)
all_data_len = len_rec + len_no_rec
print('all_data_len:', all_data_len)
img_size = 224
label = np.array([0] * len_no_rec + [1] * len_rec)
data = np.zeros((all_data_len, img_size, img_size, 3), dtype=np.uint8)
bad_image = 0
print('读取不可回收的垃圾信息!!!!!!!!!')
for i, name in enumerate(no_rec_path_list):
img = image.load_img(os.path.join(train_no_rec_path, name), target_size=(img_size, img_size))
if img is None:
print('不可回收垃圾中%s不可读取' % (os.path.join(train_no_rec_path, name)))
continue
data[i] = image.img_to_array(img)
train_rec_path = '../Dataset/tianyi/all_train/10'
rec_path_list = os.listdir(train_rec_path)
for i, name in enumerate(rec_path_list):
img = image.load_img(os.path.join(train_rec_path, name), target_size=(img_size, img_size))
if img is None:
print('可回收垃圾中%s不可读'%(os.path.join(train_rec_path, name)))
continue
data[i + len_no_rec] = image.img_to_array(img)
# 以下部分是模型的训练部分
X_train, X_val, y_train, y_val = train_test_split(data, label, shuffle=True, test_size=0.1, random_state=2019)
print('X_train, y_train:', X_train.shape, y_train.shape)
model_Dense = InceptionResNetV2(input_shape=(224, 224, 3), weights='imagenet', include_top=False)
x = model_Dense.output
print('model_Dense.output的形状是:', x.shape)
x = keras.layers.GlobalMaxPool2D()(x)
print('经过全局最大此话层之后的形状:', x.shape)
x = keras.layers.Dense(1024, kernel_regularizer=regularizers.l2(0.001), activation='relu')(x)
x = keras.layers.Dropout(0.2)(x)
y = keras.layers.Dense(1, activation='sigmoid')(x)
model_1 = Model(inputs=model_Dense.input, outputs=y)
model_1.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
model_1.fit(x=X_train, y=y_train, batch_size=16, epochs=5, validation_data=(X_val, y_val), verbose=1000, shuffle=True)
print('..............正在保存单个模型..................')
model_1.save('model/New_Try_Train_For_loadimage.h5')
方案二:
使用InceptionResNetV2和DenseNet201得到图像的中间特征,最后将两个特征进行拼接,放到全连接层进行分类。
# -*- coding: utf-8 -*-
# @Time : 2019/8/13 21:34
# @Author : YYLin
# @Email : [email protected]
# @File : ronghemoxing_for_new_dataset.py
# 本版本使用 InceptionResNetV2和DenseNet201两个模型进行融合
# 首先是使用预训练好的模型得到图像的隐层特征 然后将隐层特征进行拼接放到模型之中
# 该模型使用load_image()读取图像
import os, h5py
import numpy as np
from keras.layers import Lambda, Input
from keras.applications import InceptionResNetV2, DenseNet201
from keras import regularizers
import keras
from sklearn.model_selection import train_test_split
from keras.models import Model
from keras.preprocessing import image
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
# 读取不可回收的垃圾
train_no_rec_path = 'data/my_all_train/00'
no_rec_path_list = os.listdir(train_no_rec_path)
len_no_rec = len(no_rec_path_list)
print('len_no_rec:', len_no_rec)
# 读取可回收的垃圾
train_rec_path = 'data/my_all_train/10'
rec_path_list = os.listdir(train_rec_path)
len_rec = len(rec_path_list)
print('len_rec:', len_rec)
all_data_len = len_rec + len_no_rec
print('all_data_len:', all_data_len)
img_size = 224
label = np.array([0] * len_no_rec + [1] * len_rec)
data = np.zeros((all_data_len, img_size, img_size, 3), dtype=np.uint8)
# 数据的返回是0-255 没有将其转化成0-1之间
for i, name in enumerate(no_rec_path_list):
img = image.load_img(os.path.join(train_no_rec_path, name), target_size=(img_size, img_size))
if img is None:
print('不可回收垃圾中%s不可读取' % (os.path.join(train_no_rec_path, name)))
continue
data[i] = image.img_to_array(img)
# 读取的是可回收的垃圾
for i, name in enumerate(rec_path_list):
img = image.load_img(os.path.join(train_rec_path, name), target_size=(img_size, img_size))
if img is None:
print('可回收垃圾中%s不可读'%(os.path.join(train_rec_path, name)))
continue
data[i + len_no_rec] = image.img_to_array(img)
# 对于测试集中的图像信息 也是需要通过model.predict()得到最后的预测结果
test_path = 'data/Test_B/test'
file_list = os.listdir(test_path)
tests = []
for i, file in enumerate(file_list):
img = image.load_img(os.path.join(test_path, file), target_size=(img_size, img_size))
if img is None:
print('可回收垃圾中%s不可读' % (os.path.join(train_rec_path, file)))
continue
img = image.img_to_array(img)
tests.append(img)
test = np.array(tests)
# 开始定义自己的训练模型
def gener_fea(model, preprocess=None, name=''):
x = Input((img_size, img_size, 3))
if preprocess:
x = Lambda(preprocess)(x)
base_model = model(input_tensor=x, weights='imagenet', include_top=False, pooling='avg')
train_fea = base_model.predict(data, batch_size=32)
test_fea = base_model.predict(test, batch_size=32)
# 如果文件不存在的话 则将数据写入到模型之中
if os.path.exists("../A_model/%s.h5" % (name)):
print("../A_model/%s.h5" % (name), '已存在,不执行写操作')
else:
with h5py.File("../A_model/%s.h5" % (name), 'w') as f:
print('正在保存数据../A_model/%s' % (name))
f.create_dataset('train', data=train_fea)
f.create_dataset('test', data=test_fea)
return train_fea, test_fea
# 使用 DenseNet201 和 InceptionResNetV2 预测结果
Den_201_train, Den_201_test = gener_fea(DenseNet201, name='DenseNet201')
print('DenseNet201:', Den_201_train.shape, Den_201_test.shape)
Incep_Res_train, Incep_Res_test = gener_fea(InceptionResNetV2, name='InceptionResNetV2')
print('InceptionResNetV2:', Incep_Res_train.shape, Incep_Res_test.shape)
train = np.concatenate((Den_201_train, Incep_Res_train), axis=1)
test_for_result = np.concatenate((Den_201_test, Incep_Res_test), axis=1)
# 对数据集进行分裂 一部分作为训练集 一部分作为验证集
X_train, X_val, y_train, y_val = train_test_split(train, label, shuffle=True, test_size=0.2, random_state=2019)
# 以下是模型的输入输出部分
inputs = Input((train.shape[1],))
x = inputs
x = keras.layers.Dense(1024, kernel_regularizer=regularizers.l2(0.001), activation='relu')(x)
x = keras.layers.Dropout(0.5)(x)
y = keras.layers.Dense(1, activation='sigmoid')(x)
# 以下是模型的训练部分
model_fusion = Model(inputs=inputs, outputs=y, name='Fusion')
model_fusion.compile(loss='binary_crossentropy', optimizer='adadelta', metrics=['accuracy'])
model_fusion.summary()
model_fusion.fit(x=X_train, y=y_train, batch_size=32, epochs=50, validation_data=(X_val, y_val), verbose=1)
model_fusion.save('model/My_Multi_Model_for_B.h5')
df_test = pd.read_csv('submission_sample_for_test_B.csv')
pred_sam = model_fusion.predict(test_for_result)
df_sub = pd.concat([df_test['pic_id'], pd.Series(y)], axis=1)
df_sub.columns = ['pic_id', 'pred']
df_sub.to_csv('DenseNet201_InceptionResNetV2_baseline.csv', index=False)