前言
接前面那个系列,打不开链接,但是原来给出的GitHub链接里arch_benchmark
里有源代码-----RNSA16BitNet.py
就是比赛获得第一名的代码
RNSA16BitNet.py
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
一、代码详解
下面的几个模块都是代码里面定义的函数,先逐个解释,最后再串起来。
1.加载数据列表
base_bone_dir = '/home/1/'#相当于是一个根目录
#加载数据列表
def LoadDataList(path):
train_csvFile = open (base_bone_dir + path, 'r')
# #返回一个reader对象,利用该对象遍历csv文件中的行。
#从csv文件中读取的每一行都作为字符串列表返回。
reader = csv.reader (train_csvFile)
result = {
}
item_idx = 0
for item in reader:
if item_idx==0:
item_idx+=1
continue
result[item_idx-1] = item
item_idx += 1
train_csvFile.close ()
return result
train_list_use = LoadDataList('boneage-training-dataset.csv')
print(train_list_use)
运行结果如下,返回一个带有图片所有信息的字典。
{
0: ['10000', '96', 'TRUE'], 1: ['10001', '168', 'TRUE'], 2: ['10002', '168', 'TRUE'], 3: ['10003', '76', 'FALSE'], 4: ['10004', '135', 'TRUE'], 5: ['10005', '180', 'TRUE'], 6: ['10006', '82', 'FALSE'], 7: ['10007', '168', 'TRUE'], 8: ['10008', '36', 'FALSE']}
2.加载数据
这个函数就承接上一步函数,上一步函数得到的是数据的信息列表,这一步就是将列表里的信息加入到对应的部分。
#加载数据
def LoadData2Mem(data_list_use, img_size=500):
img_data=[]
boneage_data=[]
gender_data=[]
for i in range(len(data_list_use)):
img_name = base_bone_dir+'boneage-training-dataset/'+data_list_use[i][0]+'.png'
img = Image.open(img_name).convert('L')
img = np.array(img.resize((img_size, img_size)))
#print(img.shape)
boneage = int(data_list_use[i][1])
gender = data_list_use[i][2]
#print(gender)
if gender == 'TRUE': ##is male
gender_int=1
else:
gender_int=0
img_data.append(img)
boneage_data.append(boneage)
gender_data.append(gender_int)
#print(gender_data)
# reshape(-1,1)转换成1列:
img_data = (np.array(np.reshape(img_data, (-1, 500, 500, 1)), dtype='float32')/255.0)-0.5
# reshape(-1)转换成1行:
boneage_data = np.array(np.reshape(boneage_data,(-1,)), dtype='float32')
gender_data = np.array(np.reshape(gender_data,(-1,)), dtype='float32')
#print(gender_data)
return img_data, boneage_data, gender_data
img_train, boneage_train, gender_train=LoadData2Mem(train_list_use, 500)
#print(img_train)
print(boneage_train)
print(gender_train)
运行结果如下
[ 96. 168. 168. 76. 135. 180. 82. 168. 36.]
[1. 1. 1. 0. 1. 1. 0. 1. 0.]
最开始的代码中有报错
module 'scipy' has no attribute 'misc'
原因是版本太高,scipy.misc.imresize
已经被弃用了,可以直接用PIL的img.resize
来代替。
3.保存csv
文件
def SaveDataList(path, data_list):
#csv.writer().writerow()保存的csv文件
csvFile = open (path, 'w')
writer = csv.writer (csvFile)
writer.writerows (data_list)
csvFile.close()
4.定义预训练模型函数
def Boneage_prediction_model():
i1 = Input(shape=(500,500,1), name='input_img')
i2 = Input(shape=(1,), name='input_gender')
base = InceptionV3(input_tensor=i1, input_shape=(500,500,1), include_top=False, weights=None)
feature_img = base.get_layer(name='mixed10').output#输出特定层
#feature_img = AveragePooling2D((2,2), name='ave_pool_fea')(feature_img)
#feature_img = Flatten()(feature_img)
#feature_img = GlobalAveragePooling2D()(feature_img)
feature_img = AveragePooling2D((2,2))(feature_img)
feature_img = Flatten()(feature_img)
feature_gender = Dense(32, activation='relu')(i2)
feature = concatenate([feature_img, feature_gender], axis=1)
feature = feature_img
o = Dense(1000, activation='relu')(feature)
o = Dense(1000, activation='relu')(o)
o = Dense(1)(o)
model = Model(inputs=i1, outputs=o)
optimizer =Adam(lr=1e-3)
model.compile(loss='mean_absolute_error', optimizer=optimizer)
return model
5.调用函数
train_list_use = LoadDataList('boneage-training-dataset.csv')#调用LoadDataList,生成训练列表
val_list_use = LoadDataList('boneage-val-dataset.csv')#生成验证集的列表
num_train_sample = len(train_list_use)#训练集列表的长度,即 有多少个训练样本
num_val_sample = len(val_list_use)#验证集样本个数
#调用LoadData2Mem 生成img、gender、bneage的data
img_train, boneage_train, gender_train=LoadData2Mem(train_list_use, 500)
img_val, boneage_val, gender_val=LoadData2Mem(val_list_use, 500)
model = Boneage_prediction_model()#调用model
6.回调函数
history = History()
#filename:保存的文件名 separator:csv的分隔符 append:True-append;False-overwrite
#将每个epochs的结果保存到表格
logger = CSVLogger(base_bone_dir+'/log.csv', separator=',', append=False)
#当监视的性能指标不再提升时停止
earlystopping = EarlyStopping(monitor='val_loss', min_delta=0.01, patience=10, verbose=10, mode='min')
#每隔epochs保存模型
checkpoint = ModelCheckpoint(base_bone_dir+'weights-{epoch:02d}-{val_loss:.2f}.h5', monitor='val_loss', save_best_only=True, verbose=1, mode='min')
#当性能不在提升时改变学习率
reduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.8, patience=10, verbose=1, mode='auto', epsilon=0.0001, cooldown=5, min_lr=0.0001)
7.训练模型
#生成器,扩大数据集,增强效率
datagen = ImageDataGenerator( # 1
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=20,
zoom_range=0.2,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
vertical_flip=False)
#简单来说,就是求得训练集X的均值啊,方差啊,最大值啊,最小值啊这些训练集X固有的属性。可以理解为一个训练过程
datagen.fit(img_train)
###逐个生成数据的batch并进行训练。生成器与模型将并行执行以提高效率
#steps_per_epoch:整数,当生成器返回steps_per_epoch次数据时计一个epoch结束,执行下一个epoch
#epochs:整数,数据迭代的轮数
#validation_data:具有以下三种形式之一
##生成验证集的生成器
##一个形如(inputs,targets)的tuple
##一个形如(inputs,targets,sample_weights)的tuple
###返回一个 History 对象。其 History.history 属性是连续 epoch 训练损失和评估值,
###以及验证集损失和评估值的记录(如果适用)
###fit()函数传入的x_train和y_train是被完整的加载进内存的,当然用起来很方便
###但是如果我们数据量很大,那么是不可能将所有数据载入内存的,必将导致内存泄漏,这时候我们可以用fit_generator函数来进行训练。
model.fit_generator(datagen.flow(img_train, boneage_train, batch_size=6),
steps_per_epoch = 6,
epochs=2,
callbacks=[history, logger, earlystopping, checkpoint, reduceLROnPlat],
validation_data=(img_val, boneage_val),
verbose=1)
训练结果。。。。哈哈哈由于数据集的问题,还有epoch的问题损失很大,所以这只是一个示例。。。。哈哈哈哈
Epoch 1/2
1/6 [====>.........................] - ETA: 6:01 - loss: 129.6498
2/6 [=========>....................] - ETA: 3:36 - loss: 136.3606
3/6 [==============>...............] - ETA: 2:20 - loss: 109.7859
4/6 [===================>..........] - ETA: 1:27 - loss: 109.7451
5/6 [========================>.....] - ETA: 42s - loss: 105.3468
6/6 [==============================] - 263s 44s/step - loss: 93.6236 - val_loss: 113.1152
Epoch 00001: val_loss improved from inf to 113.11520, saving model to /home/1/weights-01-113.12.h5
Epoch 2/2
1/6 [====>.........................] - ETA: 2:27 - loss: 65.9588
2/6 [=========>....................] - ETA: 2:11 - loss: 63.8128
3/6 [==============>...............] - ETA: 1:38 - loss: 54.2574
4/6 [===================>..........] - ETA: 1:07 - loss: 50.9770
5/6 [========================>.....] - ETA: 33s - loss: 50.5726
6/6 [==============================] - 212s 35s/step - loss: 47.8267 - val_loss: 91.0097
Epoch 00002: val_loss improved from 113.11520 to 91.00973, saving model to /home/1/weights-02-91.01.h5
总结
悟了吗?!整个训练过程。。。。。就是先定义预训练模型把你所定义的model整出来,然后用model.fit()
/model.fit_generator
去训练就可以了。。。。。