首先,要先说明,我讲的这些深度学习实战项目流程,主要针对于自建数据集。
在使用前要导入需要用到的库,不然会导致代码报错。
上边博文讲了怎么打标签,接下来就是读取已经打完标签的数据。
df = pd.read_csv('train.csv')
df = df.loc[:].values #从多个维度(行和列)对读取所有数据
trainData = []
trainLabels = []
for item in df:
trainLabels.append(item[0]) #先行再列地读取数据,item[0]=标签,即第一行第一个(索引为0)的值
trainData.append(item[1:].reshape((300,100,1))) #hwc,把原来的一行改为hwc格式满足keras的输入格式。
trainLabels = np_utils.to_categorical(trainLabels, 3) # 类别
trainData = array(trainData)
model = Sequential()
model.add(Conv2D(filters=6, kernel_size=(5, 5), padding='same', input_shape=trainData.shape[1:], activation='tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=16, kernel_size=(5, 5), padding='same', activation='tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120, activation='tanh'))
model.add(Dense(84, activation='tanh'))
model.add(Dense(3, activation='softmax'))
sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(trainData, trainLabels, batch_size=64, epochs=1000, verbose=1, shuffle=True)
model.save('lenet5.h5')
在这里分享一个完整的打标签加上训练的代码。
import glob
import os
import cv2
import numpy as np
import random
import tensorflow as tf
from tensorflow import keras
tf.random.set_seed(520)
np.random.seed(520)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
assert tf.__version__.startswith('2.')
def Data_Generation():
X_data = [];
Y_data = []
path_data = [];
path_label = []
# path_file=os.getcwd() #获取当前工作目录
files = os.listdir('classification') # 获取'pokemon'文件夹下的所有文件名
for file in files:
print(file)
for path in glob.glob('classification/' + file + '/*.*'):
if 'jpg' or 'png' or 'bmp' in path: # 只获取jpg/png/bmp格式的图片
path_data.append(path)
random.shuffle(path_data) # 打乱数据
for paths in path_data: #
if '类别名1' in paths: # 为每一类打标签
path_label.append(0)
elif '类别名2' in paths:
path_label.append(1)
elif '类别名3' in paths:
path_label.append(2)
elif '类别名4' in paths:
path_label.append(3)
img = cv2.imread(paths) # 用opencv读图片数据
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # cv的图片通道是BGR,要转换成送入NN的RGB
img = cv2.resize(img, (78, 170)) # 统一图片大小
X_data.append(img)
L = len(path_data)
Y_data = path_label
X_data = np.array(X_data, dtype=float)
Y_data = np.array(Y_data, dtype='uint8')
X_train = X_data[0:int(L * 0.8)] # 将数据分为训练集 验证集和测试集 比例为 0.8:0.1:0.1
Y_train = Y_data[0:int(L * 0.8)]
X_valid = X_data[int(L * 0.8):int(L * 0.9)]
Y_valid = Y_data[int(L * 0.8):int(L * 0.9)]
X_test = X_data[int(L * 0.9):]
Y_test = Y_data[int(L * 0.9):]
return X_train, Y_train, X_valid, Y_valid, X_test, Y_test, L
X_train, Y_train, X_valid, Y_valid, X_test, Y_test, L = Data_Generation()
np.savez(os.path.join('classification','data.npz'),X_train = X_train, Y_train = Y_train, X_valid = X_valid, Y_valid = Y_valid, X_test = X_test, Y_test = Y_test)
# 打包成npz的压缩格式 储存在工程文件目录中,这样运行程序进行测试时就不用每次都重复生成数据,直接调用npz就好
读取数据代码如下:
import numpy as np
data=np.load('data.npz')
X_train=data['X_train']
Y_train=data['Y_train']
X_valid=data['X_valid']
Y_valid=data['Y_valid']
X_test= data['X_test']
Y_test= data['Y_test']
print(X_train.shape,Y_train.shape)#shape:数量,width,height,channels
print(X_valid.shape,Y_valid.shape)
print(X_test.shape,Y_test.shape)
接下来训练网络
def normalize(x):
img_mean = tf.constant([0.485, 0.456, 0.406])
img_std = tf.constant([0.229, 0.224, 0.225])
x = (x - img_mean)/img_std
return x
batchsz=32
#print(shape(X_data), shape(Y_data))
#使用 tf.data.Dataset.from_tensor_slices 进行加载
train_db = tf.data.Dataset.from_tensor_slices((X_train,Y_train))
train_db = train_db.shuffle(10000).map(preprocess).batch(batchsz)
#map预处理,预处理函数在上面有写
valid_db = tf.data.Dataset.from_tensor_slices((X_valid,Y_valid))
valid_db = valid_db.map(preprocess).batch(batchsz)
test_db = tf.data.Dataset.from_tensor_slices((X_test,Y_test))
test_db = test_db.map(preprocess).batch(batchsz)
net=keras.applications.DenseNet121(weights='imagenet',include_top=False,pooling='max')#这里使用了自带的DenseNet121网络 你也可以用keras.Sequential DIY模型
net.trainable=False
cnn_net=keras.Sequential([
net,
layers.Dense(1024,activation='relu'),
layers.BatchNormalization(), #BN层 标准化数据
layers.Dropout(rate=0.2),
layers.Dense(4)])
#其要进行转换为array矩阵,其实际格式是(batch,height,width,C)
cnn_net.build(input_shape=(4,32,32,3))
cnn_net.summary()
early_stopping=EarlyStopping( #防止过拟合
monitor='val_accuracy',
min_delta=0.01,
patience=3)
cnn_net.compile(optimizer=optimizers.Adam(lr=1e-3),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = cnn_net.fit(train_db, validation_data=valid_db, validation_freq=1, epochs=50,callbacks=[early_stopping])
history = history.history #history字典类型,包含val_loss,val_acc,loss,acc四个key值
cnn_net.evaluate(test_db)
#训练结束以后保存model文件到本地方便做图片分类的时候直接调用
#way1 保存model成 .pb 格式 方便各个平台(移动端等)的调用
tf.saved_model.save(cnn_net,'densenet')
#way2 保存model成 .h5格式 里面包含了模型结构和训练好的模型参数
cnn_net.save('densenet.h5')
test.py
import tensorflow as tf
from tensorflow import keras
import cv2
label=['0','1','2','3']
network = keras.models.load_model('densenet.h5')
network.summary()
image=cv2.imread('test.jpeg')
img=image.copy()
img=cv2.resize(img,(32,32))
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
def normalize(x):
img_mean = tf.constant([0.485, 0.456, 0.406])
img_std = tf.constant([0.229, 0.224, 0.225])
x = (x - img_mean)/img_std
return x
def preprocess(x):
x = tf.expand_dims(x,axis=0)
x = tf.cast(x, dtype=tf.float32) / 255.
x = normalize(x)
return x
img=preprocess(img)
#img= tf.cast(img, dtype=tf.uint8)
result=network(img)
result=tf.nn.softmax(result)
index=tf.argmax(result,axis=-1)
print(label[int(index)])
cv2.putText(image,label[int(index)],(166,54),cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.2, (255,0,0),2)
cv2.imshow('img',image)
cv2.waitKey()
cv2.destroyAllWindows()