这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战
ResNet实战:tensorflow2.X版本,ResNet50图像分类任务(大数据集)
摘要
本例提取了植物幼苗数据集中的部分数据做数组词多音字组词数据集,数据集共有12种类别,今天我测试抑郁症和大家一起实现tensorflow2.X版本图像分类任务,分类的模型使用ResNet50。本文实现的算法有一下几个特点:
1、自定义了图片加载方式,更加灵活高效,不用将图片一次性加载到内存中,节省内存,适合大规模数据集。
2、加载模型的预训练权重,训练时间更短。
3、数据增强选用albumentations。
训练
第一步 导入需要的数据包,设置全局参数
import numpy as np
from tensorflow.keras.optimizers import Adam
import cv2
from tensorflow.keras.preprocessing.image import img_to_array
from sklearn.model_selection import train_test_split
from tensorflow.python.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
from tensorflow.keras.applications import ResNet50
import os
import tensorflow as tf
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.models import Sequential
import albumentations
norm_size = 224
datapath = 'data/train'
EPOCHS = 20
INIT_LR = 3e-4
labelList = []
dicClass = {'Black-grass': 0, 'Charlock': 1, 'Cleavers': 2, 'Common Chickweed': 3, 'Common wheat': 4, 'Fat Hen': 5, 'Loose Silky-bent': 6,
'Maize': 7, 'Scentless Mayweed': 8, 'Shepherds Purse': 9, 'Small-flowered Cranesbill': 10, 'Sugar beet': 11}
classnum = 12
batch_size = 4
np.random.seed(42)
这里可以看出tensorflow2.0以上的版本集成了Keras,我们在使用的时候就不必单独安装Keras了,以前的代码升级到tensorflow2.0以上的版本将ke工作总结ras前面加上tensorflow即可。
tensorflow说完了,再说明一下几TensorFlow个重要的全局参数:
-
norm_size = 224 设置输入图像的大小,ResNet50默认的图片尺寸是224224。
-
datapath = ‘data/train’ 设置图片存放的路径,在这里要说明一下如果图片很多,一定不要放在工程目录下,否则数组公式Pycharm加载工程的时候会浏览所有的图片,很慢很慢。
-
EPOCHS = 20 epochs的数量,关于epoch的设置多少合适,这个问题很纠结,一般情况设置300足够了,如果感觉没有训练好,再载入模型训练。大数据技术
-
IN数组排序IT_LR = 1e-3 学习率,一般情况从0.数组去重001开始逐google渐降低,也别太小了到1e-6就可以了。
-
classnum = 12 类数组公式别数量,数数组的定义据集有两个类别,所有就分为两类。
-
batch_size = 4 batchsize,测试抑郁症的20道题根据硬件的情况和数据数组排序集的大小设置,太小了loss浮动太大,太大了收敛不好,根据经验来,一般设置为2的次方。数组指针windows可以通过任务管理器查看显存的占用情况。
Ubuntu可以使用nvidia-smi查看显存的占用。测试手机是否被监控
-
定义numpy.random的随机因子。数组指针这样就可以固定随公积金机的index
第二步 加载图片
和以前做法不同的是,这里不再处理图片,而是只返回图片路龚俊径的list列表。
具体做法详见代码:
def loadImageData():
imageList = []
listClasses = os.listdir(datapath) # 类别文件夹
print(listClasses)
for class_name in listClasses:
label_id = dicClass[class_name]
class_path = os.path.join(datapath, class_name)
image_names = os.listdir(class_path)
for image_name in image_names:
image_full_path = os.path.join(class_path, image_name)
labelList.append(label_id)
imageList.append(image_full_path)
return imageList
print("开始加载数据")
imageArr = loadImageData()
labelList = np.array(labelList)
print("加载数据完成")
做好数据之后,测试纸怀孕图片我们需要切分训练集和测试集,一般按照4:1测试手机是否被监控或者7:3的比例来切分。切分数据集使用train_test_split()方法大数据杀熟,需要导入f测试抑郁症rom测试抑郁症 sklearn.model_selection import train_test_split 包。例:
trainX, valX, trainY, valY = train_test_split(imageArr, labelList, test_size=0.2, random_state=42)
第三步 图像增强
train_transform = albumentations.Compose([
albumentations.OneOf([
albumentations.RandomGamma(gamma_limit=(60, 120), p=0.9),
albumentations.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.9),
albumentations.CLAHE(clip_limit=4.0, tile_grid_size=(4, 4), p=0.9),
]),
albumentations.HorizontalFlip(p=0.5),
albumentations.ShiftScaleRotate(shift_limit=0.2, scale_limit=0.2, rotate_limit=20,
interpolation=cv2.INTER_LINEAR, border_mode=cv2.BORDER_CONSTANT, p=1),
albumentations.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225), max_pixel_value=255.0, p=1.0)
])
val_transform = albumentations.Compose([
albumentations.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225), max_pixel_value=255.0, p=1.0)
])
这个随意写的,具体的设置可以参考我以前写的文章:
图像增强库ATensorFlowlbumentations使用总结_AI浩-CSD测试抑郁程度的问卷N博客_albumentations
写了两个数据增强,一个是用于训练,一个用于验证。验证集只需要对图片做归一数组指针化处理。
第四Go步 定义图像处理的方法
generator的主要作用是处理图像,并迭代的方式返回tensorflow2一个battensorflow是干什么的ch数组词多音字组词的图像以及对应的label。
思路:
在while循环:
-
初始化input_samples和input_labels,连个list分别用来存放image和image对应的标签。
-
循环batch_size次数:
-
- 随机一个index
- 分苟在神诡世界别从file_pathList和labels,得到图片的路径和对应的label
- 读龚俊取图片
- 如果是训练数组词就训练的transform,如果不是就执行验证的transform。
- resize图片
- 将image转数组
- 将图像和label分别放到input_samples和input_labels
-
将list转numpy数组。
-
返回一次迭代
def generator(file_pathList,labels,batch_size,train_action=False):
L = len(file_pathList)
while True:
input_labels = []
input_samples = []
for row in range(0, batch_size):
temp = np.random.randint(0, L)
X = file_pathList[temp]
Y = labels[temp]
image = cv2.imdecode(np.fromfile(X, dtype=np.uint8), -1)
if image.shape[2] > 3:
image = image[:, :, :3]
if train_action:
image=train_transform(image=image)['image']
else:
image = val_transform(image=image)['image']
image = cv2.resize(image, (norm_size, norm_size), interpolation=cv2.INTER_LANCZOS4)
image = img_to_array(image)
input_samples.append(image)
input_labels.append(Y)
batch_x = np.asarray(input_samples)
batch_y = np.asarray(input_labels)
yield (batch_x, batch_y)
第五步 保留最好的模型和动态设置学习率
ModelCheckpoint数组c语言:用来保存成绩最好的模型。
语法如下:
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)
该回调函数将在每个epoch后保存模型到filepath
filepath可以是格式化的字符串,里面的占位符将会被epoch值和传入on_epoch_end的logs关键字所填入
例如,fgoogleilep大数据技术与应用专业ath若为weights.{epoch:02d-{val_loss:.2f}}.hdf5,则会生成对应epoch和验证集loss的多个文公积金件。
参数
- filename:字符串,保存模型的路径
- mo数组排序nitor:需要监视的值
- verbose:信息展示模式,0或1
- save_best_only:当设置为True时,将只保测试手机是否被监控存在验证集上性能最好的模型
- mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_大数据与会计loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
- save_weights_o测试工程师nly:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构公积金,配置信息等)
- period:CheckPoint之间的间隔的epoch数
ReduceLROnPlateau:当评价指标不在提升时,减少学习率,语法如下:
keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', epsilon=0.0001, cooldown=0, min_lr=0)
当学习停滞时,减少2倍或10倍的学习率常常能获得较好大数据专业学什么的数组排序效果。该回调函数检测指标测试抑郁程度的问卷的情况,如果在patience数组排序个epoch中看不到模型性能提升,则减少学习率
参数
- monitor:被监测测试你适合学心理学吗的量
- factor:每次减少学习率数组去重的因子,学习率将以l大数据行程码r = l测试工程师r*factor的形式被大数据杀熟减少
- patience:当patience个epoch过去而模型测试抑郁症的20道题性能不提升时,学习率减少的动作会被触发
- mode:‘auto’,‘min’,‘tensorflow版本对应max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。
- epsilon:阈值,用来确定是否进入公积金检测值的“平原区工龄差一年工资差多少”
- cooldown:学习率减数组少后,会经过cooldown个epoch才重新进行正常操tensorflow-gpu版本作
- min_lr:学习率的下限
本例代码如下:
checkpointer = ModelCheckpoint(filepath='best_model.hdf5',
monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
reduce = ReduceLROnPlateau(monitor='val_accuracy', patience=10,
verbose=1,
factor=0.5,
min_lr=1e-6)
第六步 建立模型并训练
model = Sequential()
model.add(ResNet50(include_top=False, pooling='avg', weights='imagenet'))
model.add(Dense(classnum, activation='softmax'))
optimizer = Adam(learning_rate=INIT_LR)
model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model.fit(generator(trainX,trainY,batch_size,train_action=True),
steps_per_epoch=len(trainX) / batch_size,
validation_data=generator(valX,valY,batch_size,train_action=False),
epochs=EPOCHS,
validation_steps=len(valX) / batch_size,
callbacks=[checkpointer, reduce])
model.save('my_model.h5')
print(history)
上篇博文中没有使用预训练模型,这篇在使用的时候,出现了错误,经大数据行程码过查阅资料发现了这种方式是错误的,如下:
#model = ResNet50(weights="imagenet",input_shape=(224,224,3),include_top=False, classes=classnum) #include_top=False 去掉最后的全连接层
如果想指定classes,有两个条件:include_top:True, weights:None。否则无法指定cltensorflow怎么读asses。
所以指定classes大数据专业学什么就不能用预训练了,所以采用另一种方式:
model = Sequential()
model.add(ResNet50(include_top=False, pooling='avg', weights='imagenet'))
model.add(Dense(classnum, activation='softmax'))
另外,上篇文章使用的是fit_generator,新版本中f工作总结it支持generator方式,所以改为fit。
第六步 保留训练结果,并将其生成图片
loss_trend_graph_path = r"WW_loss.jpg"
acc_trend_graph_path = r"WW_acc.jpg"
import matplotlib.pyplot as plt
print("Now,we start drawing the loss and acc trends graph...")
# summarize history for accuracy
fig = plt.figure(1)
plt.plot(history.history["accuracy"])
plt.plot(history.history["val_accuracy"])
plt.title("Model accuracy")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(["train", "test"], loc="upper left")
plt.savefig(acc_trend_graph_path)
plt.close(1)
# summarize history for loss
fig = plt.figure(2)
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.title("Model loss")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(["train", "test"], loc="upper left")
plt.savefig(loss_trend_graph_path)
plt.close(2)
print("We are done, everything seems OK...")
# #windows系统设置10关机
#os.system("shutdown -s -t 10")
测试部分
单张图片预测
1、导入依赖
import cv2
import numpy as np
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
import time
import os
import albumentations
2、设置全局参测试抑郁症的20道题数
这里注意,字典的顺序和训练时的顺序保持一致
norm_size=224
imagelist=[]
emotion_labels = {
0: 'Black-grass',
1: 'Charlock',
2: 'Cleavers',
3: 'Common Chickweed',
4: 'Common wheat',
5: 'Fat Hen',
6: 'Loose Silky-bent',
7: 'Maize',
8: 'Scentless Mayweed',
9: 'Shepherds Purse',
10: 'Small-flowered Cranesbill',
11: 'Sugar beet',
}
3、设测试智商置图片归一化参数
归一化参数的设置和验证的参数保持一致
val_transform = albumentations.Compose([
albumentations.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225), max_pixel_value=255.0, p=1.0)
])
3、加载模型
emotion_classifier=load_model("my_model.h5")
4、处理图片
处理图片的逻辑和训练集也类似,步骤:
- 读取图片
- 将图片r数组词三声esize为norm_sizenorm_size大小。
- 将图片转为数组。
- 放到imagelist中。
- 将list转为numpy数组。
image = cv2.imdecode(np.fromfile('data/test/0a64e3e6c.png', dtype=np.uint8), -1)
image = val_transform(image=image)['image']
image = cv2.resize(image, (norm_size, norm_size), interpolation=cv2.INTER_LANCZOS4)
image = img_to_array(image)
imagelist.append(image)
imageList = np.array(imagelist, dtype="float")
5、预测类别
预测类别,并获取最高类别测试你的自卑程度的index。
pre=np.argmax(emotion_classifier.predict(imageList))
emotion = emotion_labels[pre]
t2=time.time()
print(emotion)
t3=t2-t1
print(t3)
批量预测
批量预测和单张预测的差别主要在读取数据上,以及预测完成后,对预测类别的处理。其他的没有变化。
步骤:
- 加载模型。
- 定义测试集的目录
- 获取目录下的图片
- 循环循环图片
- 读取图片
- 对图片做归一化处理。
- resize图片
- 转数组tensorflow-gpu版本
- 放到imageList中
- 预测
predict_dir = 'data/test'
test11 = os.listdir(predict_dir)
for file in test11:
filepath=os.path.join(predict_dir,file)
image = cv2.imdecode(np.fromfile(filepath, dtype=np.uint8), -1)
image = val_transform(image=image)['image']
image = cv2.resize(image, (norm_size, norm_size), interpolation=cv2.INTER_LANCZOS4)
image = img_to_array(image)
imagelist.append(image)
imageList = np.array(imagelist, dtype="float")
out = emotion_classifier.predict(imageList)
print(out)
pre = [np.argmax(i) for i in out]
class_name_list=[emotion_labels[i] for i in pre]
print(class_name_list)
t2 = time.time()
t3 = t2 - t1
print(t3)
完整代码: download.ctensorflow和pytorch的区别sdn.ne大数据专业学什么t/do数组词三声wnload/hh…