700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > PowerSensorAI 3 从现有模型迁移训练 - 五花分类

PowerSensorAI 3 从现有模型迁移训练 - 五花分类

时间:2021-04-27 22:30:03

相关推荐

PowerSensorAI 3 从现有模型迁移训练 - 五花分类

文章目录

效果展示图文教程PC训练模型数据集准备与预处理网络设计与预训练DNNDK 编译EDGE调用

效果展示

要什么openMV,来试试Powersensor吧 - 深度学习 - 五花分类

图文教程

案例资料包:

链接:/s/1bqxA2homcCQ1durTJDH2TQ

提取码:knhd

Anaconda安装教程地址

/linxiaobo110/article/details/106420769

虚拟机下载地址:

链接:/s/1mdZV9jn74RCxKp_pUh4mew

提取码:623k

powersensor镜像下载地址:

链接:/s/18CFK2aXonxuFF6-L_ittdw

提取码:8ve4

对于一些简单的分类问题,如PowerSensor AI 1中的ministFashion,随手设计一个简单的深度网络就可以得到较好的分类效果。然而,这样的手法对于复杂一些的数据集很难保证效果。对于复杂的分类问题,使用已发布的精心设计的神经网络作为基础网络是更明智的选择。同时,从头开始训练深度的神经网络是一个繁重的工作,使用别人在imagenet上预训练好的权值来初始化我们的网络可以起到事半功倍的效果。本节我们将以五花分类问题(虽然这个问题不见得多复杂)为例,给大家介绍如何把tensorflow2.0官方训练好的InceptionV3,通过简单的几步操作,迁移到我们自己的数据集上使用,并在powersensor上验证运行。

经过上一讲的学习,我们已经知道DPU的应用开发流程分为PC模型训练、DNNDK模型编译、EDGE模型部署,三个步骤,本章剩下的内容将逐个介绍。

PC训练模型

首先我们需要包含一些重要的头文件和定义重要的参数

import cv2import numpy as npimport osimport tensorflow as tffrom tensorflow import kerasimport randomimport timeimport matplotlib.pyplot as plt# gpus = tf.config.experimental.list_physical_devices(device_type='GPU')# cpus = tf.config.experimental.list_physical_devices(device_type='CPU')# print(gpus, cpus)# for gpu in gpus:#tf.config.experimental.set_memory_growth(gpu, True)# 让Matplotlib正确显示中文import matplotlib as mplmpl.style.use('seaborn')mpl.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文mpl.rcParams['axes.unicode_minus']=False# 正常显示负号# 训练用的图像尺寸img_size_net = 128# 训练的batch大小batch_size = 32# 数据库路径dataset_path = '../dataset/'# 各个花的路径flower_pathes = ['flowers/daisy', 'flowers/dandelion', 'flowers/rose', 'flowers/sunflower', 'flowers/tulip']wordlist = ['雏菊', '蒲公英', '玫瑰', '向日葵', '郁金香']# 存放过程和结构的路径run_path = './run/'if not os.path.exists(run_path):os.mkdir(run_path)# 存放转换后的tf数据集的路径dataset_tf_path = run_path + 'flowersTf.tfrecords'dataset_nums = 4300

数据集准备与预处理

本节使用数据集是五花(玫瑰、向日葵、蒲公英、郁金香、雏菊)数据集,可以在我们的百度网盘数据集文件夹里下载到。下载完解压到flower_classification的dataset目录下,如下图所示:

在数据集预处理上,我们使用了上一章“石头剪刀布”识别的方案,先把原图像处理后转换为tf-recorder,然后再使用tfrecoder完成样本训练。

tick_begin = time.time()img_cnt = int(0)label_cnt = int(0)with tf.io.TFRecordWriter(dataset_tf_path) as writer:for sort_path in flower_pathes: flower_list = os.listdir(dataset_path + sort_path)for img_name in flower_list:img_path = dataset_path + sort_path + "/" + img_nameimg = cv2.imread(img_path) img_scale = cv2.resize(img,(img_size_net, img_size_net), interpolation = cv2.INTER_CUBIC)if not img is None:feature = {'img1':tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_scale.tostring()])),'label':tf.train.Feature(int64_list=tf.train.Int64List(value=[label_cnt]))# 'label':tf.train.Feature(int64_list=tf.train.Int64List(value=[label_cnt]))}example = tf.train.Example(features=tf.train.Features(feature=feature))writer.write(example.SerializeToString())# 每隔50张打印一张图片if img_cnt % 100 == 0:print('The ', str(img_cnt), ' image')plt.imshow(cv2.cvtColor(img_scale, cv2.COLOR_BGR2RGB))plt.show()img_cnt += 1label_cnt = label_cnt + 1writer.close() tick_end = time.time()print('Generate the dataset complete! Experied ', str(tick_end - tick_begin))print('The dataset is ', dataset_tf_path)

读取和测试数据集,生成数据集只需要运行一次就会自动保存到相应的目录。读取数据集在每次重启jupyter的时候都需要加载一次。

def read_and_decode(example_proto):'''从TFrecord格式文件中读取数据'''image_feature_description = {'img1':tf.io.FixedLenFeature([],tf.string),'label':tf.io.FixedLenFeature([1], tf.int64),}feature_dict = tf.io.parse_single_example(example_proto, image_feature_description)img1 = tf.io.decode_raw(feature_dict['img1'], tf.uint8)label = feature_dict['label']return img1, label# 1. 读取数据集dataset = tf.data.TFRecordDataset(dataset_tf_path)dataset = dataset.map(read_and_decode)# 2. 随机打印8个测试图像dataset = dataset.shuffle(buffer_size=dataset_nums)dataSet = np.array([x1 for x1 in dataset.take(10)])dataSet_img = np.array([x1[0].numpy() for x1 in dataSet])dataSet_img = dataSet_img.reshape((-1,img_size_net,img_size_net, 3)) / ((np.float32)(255.))dataSet_label = np.array([x1[1].numpy()[0] for x1 in dataSet]) fig, ax = plt.subplots(5, 2)fig.set_size_inches(15,15)l = 0for i in range(5):for j in range(2):ax[i, j].imshow(cv2.cvtColor(dataSet_img[l], cv2.COLOR_BGR2RGB))ax[i, j].set_title(wordlist[dataSet_label[l]])l += 1plt.tight_layout()

网络设计与预训练

训练集和测试集的打乱和重排,打乱和重排数据集可以打打减小训练不稳定的风险。

# 1. 打乱数据集dataset = dataset.shuffle(buffer_size=dataset_nums)# 2. 抓取数据集dataSet = np.array([x1 for x1 in dataset.take(dataset_nums)])dataSet_img = np.array([x1[0].numpy() for x1 in dataSet])dataSet_img = dataSet_img.reshape((-1,img_size_net,img_size_net, 3)) / ((np.float32)(255.))dataSet_label = np.array([x1[1].numpy()[0] for x1 in dataSet]) # 3. 分离训练集和测试集trainSet_num = int(0.75 * dataset_nums)trainSet_img = dataSet_img[0 : trainSet_num, :, :, :]testSet_img = dataSet_img[trainSet_num : , :, :, :]trainSet_label = dataSet_label[0 : trainSet_num]testSet_label = dataSet_label[trainSet_num : ]# 3. 统计各种训练集中各种样本的数量print('数据集中各个样本的数量:')l = []for x in dataSet_label:l.append(wordlist[x])plt.hist(l, rwidth=0.5)plt.show()

网络设计,对于minist哪种简单的数据集,我们可以随手搭一个自己的网络就可以有不俗的表现,这对于复杂一些的数据集很难保证效果。对于复杂的分类问题,使用已发布的精心设计的神经网络作为基础网络是更明智的选择。同时,从头开始训练深度的神经网络是一个繁重的工作,使用别人在imagenet上预训练好的权值来初始化我们的网络可以起到事半功倍的效果。

input_tensor = tf.keras.layers.Input(shape=(img_size_net,img_size_net,3), name="x_input")base_model = tf.keras.applications.InceptionV3(weights='imagenet', include_top=False, input_tensor=input_tensor, input_shape=(img_size_net,img_size_net,3))base_model.summary() #打印网络结构

一般来说,为了更高的效率,我们不需要整个网络,我们从输入开始,截取到输出为6x6的最后一个激活层。接上我们自己的全连接层和输出层,生成我们自己的网络:

base_model = tf.keras.Model(inputs=input_tensor, outputs=base_model.get_layer('activation_74').output)# 添加全局平均池化层x = base_model.outputx = tf.keras.layers.GlobalAveragePooling2D()(x)# 添加一个全连接层x = tf.keras.layers.Dense(64, activation='relu')(x)x = tf.keras.layers.Dropout(0.5)(x)# 添加一个分类器,假设我们有200个类predictions = tf.keras.layers.Dense(5, activation='softmax', name='y_out')(x)# 构建我们需要训练的完整模型model = tf.keras.Model(inputs=input_tensor, outputs=predictions)# 首先,我们只训练顶部的几层(随机初始化的层)# 锁住所有 InceptionV3 的卷积层for layer in model.layers[:195]:layer.trainable = Falsefor layer in model.layers[195:]:layer.trainable = True# 编译模型(一定要在锁层以后操作)pile(optimizer='rmsprop', loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy'])model.summary() #打印网络结构

训练,首先用较大的学习率训练:

history = model.fit(trainSet_img, trainSet_label, batch_size=batch_size, epochs=20, validation_data=(testSet_img, testSet_label))

然后,放开更多的层,用较小的学习率训练:

# 我们锁住前面135层,然后放开之后的层。for layer in model.layers[:135]:layer.trainable = Falsefor layer in model.layers[135:]:layer.trainable = True# 我们需要重新编译模型,才能使上面的修改生效# 让我们设置一个很低的学习率,使用 SGD 来微调 from tensorflow.keras.optimizers import pile(optimizer=SGD(lr=0.0001, momentum=0.9), loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy'])history = model.fit(trainSet_img, trainSet_label, batch_size=batch_size, epochs=20, validation_data=(testSet_img, testSet_label))

保存模型

model.save_weights(run_path + "model_weight.h5")json_config = model.to_json()with open(run_path + 'model_config.json', 'w') as json_file:json_file.write(json_config)

模型验证部分详情见源代码

使用记事本查看生成的model_config.json,如果在输入里出现"ragged": false,字眼的字段,请手动把它删掉,因为dnndk里的tensorflow没有这个参数。没有就不用处理。

DNNDK 编译

同minisFashiont的例子,我们将在DNNDK里将模型编译成DPU能够运行的模型。

启动虚拟机在虚拟机的/home/xiaobo/powersensor目录下新建flowerFive文件夹,并把案例目录下的dnndk文件夹和dataset_valid文件夹复制到新建的文件夹下面。如果要使用自己新训练的模型,需要把自己的模型(在案例目录/pc/run下面的2个模型文件)替换掉我们准备好的文件。进入dnndk目录,右击启动shell,使用下面指令固化模型

./1_vitisAI_keras2frozon.sh

第二步,量化,注意把2_vitisAI_tf_quantize.sh中的input_nodesinput_shapesoutput_nodes改成与第一步打印的节点名称一致。

./2_vitisAI_tf_quantize.sh

第三步,编译模型

./3_vitisAI_tf_compile.sh

编译的结果在compile_result文件夹里,里面的.elf文件就是编译好的模型。

EDGE调用

进入powersenosr的jupyter文件管理页面,在/powersensor_workspace/powersensor_ai下面新建flowerFive目录(随教程发布的案例已经准备好文件了)。在新建的flowerFive目录下新建dataset_validedge文件夹

通过jupyter的上传功能,把案例目录下的edge文件夹下的两个文件上传到powersensor的edge目录;验证集dataset_valid下的文件也同理上传到相应目录。

如果要使用自己新训练的模型,可以把edge下的elf换成虚拟机里的compileResult下的elf文件。注意虚拟机里的文件不能直接上传(找不到),要先拷贝到自己的电脑里才能上传。

打开powersensor的edge下的powersensor_ministNumer.ipynb文件,按照notebook里面的指导逐个运行程序。

首先也是加载头文件和重要的参数,其中DPU网络参数应该与DPU的编译结果输出保持一致,否则会导致DPU崩溃。

from dnndk import n2cubeimport numpy as npfrom numpy import float32import osimport cv2import matplotlib.pyplot as pltimport randomimport timeimport matplotlib as mplfrom matplotlib import font_managerimport PowerSensor as psfrom IPython.display import clear_outputmpl.rcParams['axes.unicode_minus']=False# 正常显示负号font = font_manager.FontProperties(fname="/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf")# 训练用的图像尺寸img_size_net = 128# 训练的batch大小batch_size = 32wordlist = ['雏菊', '蒲公英', '玫瑰', '向日葵', '郁金香']# DPU网络参数# KERNEL_CONV="testModel"ELF_NAME = "dpu_testModel_0.elf"CONV_INPUT_NODE = "x_input_Conv2D"CONV_OUTPUT_NODE = "y_out_MatMul"

读取测试集

dataset_path = '../dataset_valid/'(validSet_images, validSet_lables) = load_valid_data(dataset_path)# 2. 图像预处理# test_images = test_images.reshape((-1,28,28,1)) / 255.validSet_images = np.array(validSet_images, dtype='float32')# 3. 随机打印8个测试图像fig, ax = plt.subplots(5, 2)fig.set_size_inches(15,15)for i in range(5):for j in range(2):l = random.randint(0, len(validSet_lables))ax[i, j].imshow(cv2.cvtColor(validSet_images[l], cv2.COLOR_BGR2RGB))title = wordlist[validSet_lables[l]]title_utf8 = title.decode('utf8')ax[i, j].set_title(title_utf8, fontproperties=font)plt.tight_layout()

加载dpu

dpu1 = ps.DpuHelper()dpu1.load_kernel(ELF_NAME, input_node_name=CONV_INPUT_NODE, output_node_name=CONV_OUTPUT_NODE)

测试集精度测试

tick_start = time.time()test_num = len(validSet_lables)right_eg_cnt = 0for i in range(test_num):img1_scale = validSet_images[i]softmax = dpu1.predit_softmax(img1_scale)pdt= np.argmax(softmax, axis=0)if pdt == validSet_lables[i]:right_eg_cnt += 1tick_end = time.time()print('精度: ' + str((right_eg_cnt*1.) / test_num))print('测试 ' + str(test_num) + ' 个样本。耗时 ' + str(tick_end - tick_start) + '秒!')############################## 精度: 1.0# 测试 50 个样本。耗时 9.1545650959秒!

随机样本测试

fig, ax = plt.subplots(5, 2)fig.set_size_inches(15,15)for i in range(5):for j in range(2):l = random.randint(0, len(validSet_lables)-1)img1_scale = validSet_images[l]softmax = dpu1.predit_softmax(img1_scale)pdt= np.argmax(softmax, axis=0)ax[i, j].imshow(cv2.cvtColor(validSet_images[l], cv2.COLOR_BGR2RGB))# title = "预测:" + str(wordlist[pdt]) + "\n" + "真实:" + str(wordlist[test_labels[l]])title = "预测:" + wordlist[pdt] + "\n" + "真实:" + wordlist[validSet_lables[l]]title_utf8 = title.decode('utf8')ax[i, j].set_title(title_utf8, fontproperties=font)plt.tight_layout()

拍照测试

# 这个对象用于操作摄像头cam1 = ps.ImageSensor()cv_font = cv2.freetype.createFreeType2()cv_font.loadFontData(fontFileName='/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf', id=0)

for i in range(100):# 记录时间start = time.time()# 清空显示区clear_output(wait=True)# 读取图像imgMat = cam1.read_img_ori()imgShow = cv2.resize(imgMat, (320,240))#imgMat_cali = grey_world2(imgMat)# 图像缩放,太大的图像显示非常浪费资源tempImg = cv2.resize(imgMat, (128,128))img_scale = tempImg / 255.img_scale = np.array(img_scale, dtype=np.float32)softmax = dpu1.predit_softmax(img_scale)pdt= np.argmax(softmax, axis=0)cv_font.putText(imgShow,wordlist[pdt], (10,10), fontHeight=30, color=(255,255,255), thickness=-1, line_type=cv2.LINE_4, bottomLeftOrigin=False)#tempImg = imgMat# 显示图像img = monFunction.show_img_jupyter(imgShow)# 记录运行时间end = time.time()# 打印运行时间print(end - start)# 因为网络传输的延时,需要稍息一下time.sleep(0.1)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。