日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用自己的数据集训练MobileNet、ResNet实现图像分类(TensorFlow)

發布時間:2024/4/15 编程问答 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用自己的数据集训练MobileNet、ResNet实现图像分类(TensorFlow) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用自己的數據集訓練MobileNet、ResNet實現圖像分類(TensorFlow)

之前鄙人寫了一篇博客《使用自己的數據集訓練GoogLenet InceptionNet V1 V2 V3模型(TensorFlow)》https://panjinquan.blog.csdn.net/article/details/81560537,本博客就是此博客的框架基礎上,完成對MobileNet的圖像分類模型的訓練,其相關項目的代碼也會統一更新到一個Github中,強烈建議先看這篇博客《使用自己的數據集訓練GoogLenet InceptionNet V1 V2 V3模型(TensorFlow)》后,再來看這篇博客。

TensorFlow官網中使用高級API -slim實現了很多常用的模型,如VGG,GoogLenet V1、V2和V3以及MobileNet、resnet模型:可詳看這里https://github.com/tensorflow/models/tree/master/research/slim,當然TensorFlow官網也提供了訓練這些模型的腳本文件,但靈活性太差了,要想增加log或者其他信息,真的很麻煩。本人花了很多時間,去搭建一個較為通用的模型訓練框架《tensorflow_models_nets》,目前幾乎可以支持所有模型的訓練,由于訓練過程是自己構建的,所以你可以在此基礎上進行任意的修改,也可以搭建自己的訓練模型。

重要說明

(1)項目Github源碼:https://github.com/PanJinquan/tensorflow_models_learning,麻煩給個“Star”

(2)你需要一臺顯卡不錯的服務器,不然會卡的一比,慢到花都謝了

(2)對于MobileNet、resnet等大型的網絡模型,重頭開始訓練,是很難收斂的。但遷移學習finetune部分我還沒有實現,大神要是現實了,分享一下哈。

(3)注意訓練mobilenet時,在迭代10000次以前,loss和準確率幾乎不會提高。一開始我以為是訓練代碼寫錯了,后來尋思了很久,才發現是模型太復雜了,所以收斂慢的一比,大概20000次迭代后,準確率才開始蹭蹭的往上長,迭代十萬次后準確率才70%,


目錄

使用自己的數據集訓練MobileNet圖像識別(TensorFlow)

1、項目文件結構說明?

2、MobileNet的網絡:

3、圖片數據集

4、制作tfrecords數據格式

5、MobileNet模型

6、訓練方法實現過程

7、模型預測

8、其他模型訓練方法?


1、項目文件結構說明?

tensorflow_models_nets:

|__dataset???#數據文件

????|__record #里面存放record文件

????|__train????#train原始圖片

????|__val??????#val原始圖片

|__models??#保存訓練的模型

|__slim????????#這個是拷貝自slim模塊:https://github.com/tensorflow/models/tree/master/research/slim

|__test_image #存放測試的圖片

|__create_labels_files.py #制作trian和val TXT的文件

|__create_tf_record.py #制作tfrecord文件

|__inception_v1_train_val.py #inception V1的訓練文件

|__inception_v3_train_val.py # inception V3訓練文件

|__mobilenet_train_val.py#mobilenet訓練文件

|__resnet_v1_train_val.py#resnet訓練文件

|__predict.py # 模型預測文件

2、MobileNet的網絡:

關于MobileNet模型,請詳看這篇博客《輕量級網絡--MobileNet論文解讀》https://blog.csdn.net/u011974639/article/details/79199306?,本博客不會糾結于模型原理和論文,主要分享的是用自己的數據集去訓練MobileNet的方法。

3、圖片數據集

下面是我下載的數據集,共有五類圖片,分別是:flower、guitar、animal、houses和plane,每組數據集大概有800張左右。為了照顧網友,下面的數據集,都已經放在Github項目的文件夾dataset上了,不需要你下載了,記得給個“star”哈

animal:http://www.robots.ox.ac.uk/~vgg/data/pets/?
flower:http://www.robots.ox.ac.uk/~vgg/data/flowers/?
plane:http://www.robots.ox.ac.uk/~vgg/data/airplanes_side/airplanes_side.tar?
house:http://www.robots.ox.ac.uk/~vgg/data/houses/houses.tar?
guitar:http://www.robots.ox.ac.uk/~vgg/data/guitars/guitars.tar?

????下載圖片數據集后,需要劃分為train和val數據集,前者用于訓練模型的數據,后者主要用于驗證模型。這里提供一個create_labels_files.py腳本,可以直接生成訓練train和驗證val的數據集txt文件。

#-*-coding:utf-8-*- """@Project: googlenet_classification@File : create_labels_files.py@Author : panjq@E-mail : pan_jinquan@163.com@Date : 2018-08-11 10:15:28 """import os import os.pathdef write_txt(content, filename, mode='w'):"""保存txt數據:param content:需要保存的數據,type->list:param filename:文件名:param mode:讀寫模式:'w' or 'a':return: void"""with open(filename, mode) as f:for line in content:str_line = ""for col, data in enumerate(line):if not col == len(line) - 1:# 以空格作為分隔符str_line = str_line + str(data) + " "else:# 每行最后一個數據用換行符“\n”str_line = str_line + str(data) + "\n"f.write(str_line) def get_files_list(dir):'''實現遍歷dir目錄下,所有文件(包含子文件夾的文件):param dir:指定文件夾目錄:return:包含所有文件的列表->list'''# parent:父目錄, filenames:該目錄下所有文件夾,filenames:該目錄下的文件名files_list = []for parent, dirnames, filenames in os.walk(dir):for filename in filenames:# print("parent is: " + parent)# print("filename is: " + filename)# print(os.path.join(parent, filename)) # 輸出rootdir路徑下所有文件(包含子文件)信息curr_file=parent.split(os.sep)[-1]if curr_file=='flower':labels=0elif curr_file=='guitar':labels=1elif curr_file=='animal':labels=2elif curr_file=='houses':labels=3elif curr_file=='plane':labels=4files_list.append([os.path.join(curr_file, filename),labels])return files_listif __name__ == '__main__':train_dir = 'dataset/train'train_txt='dataset/train.txt'train_data = get_files_list(train_dir)write_txt(train_data,train_txt,mode='w')val_dir = 'dataset/val'val_txt='dataset/val.txt'val_data = get_files_list(val_dir)write_txt(val_data,val_txt,mode='w')

注意,上面Python代碼,已經定義每組圖片對應的標簽labels:

flower ->labels=0 guitar ->labels=1 animal ->labels=2 houses ->labels=3 plane ->labels=4

4、制作tfrecords數據格式

有了 train.txt和val.txt數據集,我們就可以制作train.tfrecords和val.tfrecords文件了,項目提供一個用于制作tfrecords數據格式的Python文件:create_tf_record.py,鄙人已經把代碼放在另一篇博客:《Tensorflow生成自己的圖片數據集TFrecords》https://blog.csdn.net/guyuealian/article/details/80857228?,代碼有詳細注釋了,所以這里不貼出來了.

注意:

(1)create_tf_record.py將train和val數據分別保存為單個record文件,當圖片數據很多時候,會導致單個record文件超級巨大的情況,解決方法就是,將數據分成多個record文件保存,讀取時,只需要將多個record文件的路徑列表交給“tf.train.string_input_producer”即可。

(2)如何將數據保存為多個record文件呢?請參考鄙人的博客:《Tensorflow生成自己的圖片數據集TFrecords》https://blog.csdn.net/guyuealian/article/details/80857228

為了方便大家,項目以及適配了“create_tf_record.py”文件,dataset已經包含了訓練和測試的圖片,請直接運行create_tf_record.py即可生成tfrecords文件。

對于InceptionNet V1:設置resize_height和resize_width = 224?
對于InceptionNet V3:設置resize_height和resize_width = 299?
其他模型,請根據輸入需要設置resize_height和resize_width的大小

if __name__ == '__main__':# 參數設置resize_height = 224 # 指定存儲圖片高度resize_width = 224 # 指定存儲圖片寬度shuffle=Truelog=5# 產生train.record文件image_dir='dataset/train'train_labels = 'dataset/train.txt' # 圖片路徑train_record_output = 'dataset/record/train{}.tfrecords'.format(resize_height)create_records(image_dir,train_labels, train_record_output, resize_height, resize_width,shuffle,log)train_nums=get_example_nums(train_record_output)print("save train example nums={}".format(train_nums))# 產生val.record文件image_dir='dataset/val'val_labels = 'dataset/val.txt' # 圖片路徑val_record_output = 'dataset/record/val{}.tfrecords'.format(resize_height)create_records(image_dir,val_labels, val_record_output, resize_height, resize_width,shuffle,log)val_nums=get_example_nums(val_record_output)print("save val example nums={}".format(val_nums))# 測試顯示函數# disp_records(train_record_output,resize_height, resize_width)batch_test(train_record_output,resize_height, resize_width)

? create_tf_record.py提供幾個重要的函數:

  • create_records():用于制作records數據的函數,
  • read_records():用于讀取records數據的函數,
  • get_batch_images():用于生成批訓練數據的函數
  • get_example_nums:統計tf_records圖像的個數(example個數)
  • disp_records():?解析record文件,并顯示圖片,主要用于驗證生成record文件是否成功
  • 5、MobileNet模型

    ? 官網TensorFlow已經提供了使用TF-slim實現的MobileNet模型。

    1、官網模型地址:https://github.com/tensorflow/models/tree/master/research/slim/nets

    2、slim/nets下的模型都是用TF-slim實現的網絡結構,關系TF-slim的用法,可參考:

    《tensorflow中slim模塊api介紹》:https://blog.csdn.net/guvcolie/article/details/77686555

    6、訓練方法實現過程

    訓練文件源碼已經給了較為詳細的注釋,不明白請在評論區留言吧

    #coding=utf-8import tensorflow as tf import numpy as np import pdb import os from datetime import datetime import slim.nets.mobilenet_v1 as mobilenet_v1 from create_tf_record import * import tensorflow.contrib.slim as slim''' 參考資料:https://www.cnblogs.com/adong7639/p/7942384.html ''' labels_nums = 5 # 類別個數 batch_size = 16 # resize_height = 224 # mobilenet_v1.default_image_size 指定存儲圖片高度 resize_width = 224 # mobilenet_v1.default_image_size 指定存儲圖片寬度 depths = 3 data_shape = [batch_size, resize_height, resize_width, depths]# 定義input_images為圖片數據 input_images = tf.placeholder(dtype=tf.float32, shape=[None, resize_height, resize_width, depths], name='input') # 定義input_labels為labels數據 # input_labels = tf.placeholder(dtype=tf.int32, shape=[None], name='label') input_labels = tf.placeholder(dtype=tf.int32, shape=[None, labels_nums], name='label')# 定義dropout的概率 keep_prob = tf.placeholder(tf.float32,name='keep_prob') is_training = tf.placeholder(tf.bool, name='is_training')def net_evaluation(sess,loss,accuracy,val_images_batch,val_labels_batch,val_nums):val_max_steps = int(val_nums / batch_size)val_losses = []val_accs = []for _ in range(val_max_steps):val_x, val_y = sess.run([val_images_batch, val_labels_batch])# print('labels:',val_y)# val_loss = sess.run(loss, feed_dict={x: val_x, y: val_y, keep_prob: 1.0})# val_acc = sess.run(accuracy,feed_dict={x: val_x, y: val_y, keep_prob: 1.0})val_loss,val_acc = sess.run([loss,accuracy], feed_dict={input_images: val_x, input_labels: val_y, keep_prob:1.0, is_training: False})val_losses.append(val_loss)val_accs.append(val_acc)mean_loss = np.array(val_losses, dtype=np.float32).mean()mean_acc = np.array(val_accs, dtype=np.float32).mean()return mean_loss, mean_accdef step_train(train_op,loss,accuracy,train_images_batch,train_labels_batch,train_nums,train_log_step,val_images_batch,val_labels_batch,val_nums,val_log_step,snapshot_prefix,snapshot):'''循環迭代訓練過程:param train_op: 訓練op:param loss: loss函數:param accuracy: 準確率函數:param train_images_batch: 訓練images數據:param train_labels_batch: 訓練labels數據:param train_nums: 總訓練數據:param train_log_step: 訓練log顯示間隔:param val_images_batch: 驗證images數據:param val_labels_batch: 驗證labels數據:param val_nums: 總驗證數據:param val_log_step: 驗證log顯示間隔:param snapshot_prefix: 模型保存的路徑:param snapshot: 模型保存間隔:return: None'''saver = tf.train.Saver(max_to_keep=5)max_acc = 0.0with tf.Session() as sess:sess.run(tf.global_variables_initializer())sess.run(tf.local_variables_initializer())coord = tf.train.Coordinator()threads = tf.train.start_queue_runners(sess=sess, coord=coord)for i in range(max_steps + 1):batch_input_images, batch_input_labels = sess.run([train_images_batch, train_labels_batch])_, train_loss = sess.run([train_op, loss], feed_dict={input_images: batch_input_images,input_labels: batch_input_labels,keep_prob: 0.8, is_training: True})# train測試(這里僅測試訓練集的一個batch)if i % train_log_step == 0:train_acc = sess.run(accuracy, feed_dict={input_images: batch_input_images,input_labels: batch_input_labels,keep_prob: 1.0, is_training: False})print("%s: Step [%d] train Loss : %f, training accuracy : %g" % (datetime.now(), i, train_loss, train_acc))# val測試(測試全部val數據)if i % val_log_step == 0:mean_loss, mean_acc = net_evaluation(sess, loss, accuracy, val_images_batch, val_labels_batch, val_nums)print("%s: Step [%d] val Loss : %f, val accuracy : %g" % (datetime.now(), i, mean_loss, mean_acc))# 模型保存:每迭代snapshot次或者最后一次保存模型if (i % snapshot == 0 and i > 0) or i == max_steps:print('-----save:{}-{}'.format(snapshot_prefix, i))saver.save(sess, snapshot_prefix, global_step=i)# 保存val準確率最高的模型if mean_acc > max_acc and mean_acc > 0.7:max_acc = mean_accpath = os.path.dirname(snapshot_prefix)best_models = os.path.join(path, 'best_models_{}_{:.4f}.ckpt'.format(i, max_acc))print('------save:{}'.format(best_models))saver.save(sess, best_models)coord.request_stop()coord.join(threads)def train(train_record_file,train_log_step,train_param,val_record_file,val_log_step,labels_nums,data_shape,snapshot,snapshot_prefix):''':param train_record_file: 訓練的tfrecord文件:param train_log_step: 顯示訓練過程log信息間隔:param train_param: train參數:param val_record_file: 驗證的tfrecord文件:param val_log_step: 顯示驗證過程log信息間隔:param val_param: val參數:param labels_nums: labels數:param data_shape: 輸入數據shape:param snapshot: 保存模型間隔:param snapshot_prefix: 保存模型文件的前綴名:return:'''[base_lr,max_steps]=train_param[batch_size,resize_height,resize_width,depths]=data_shape# 獲得訓練和測試的樣本數train_nums=get_example_nums(train_record_file)val_nums=get_example_nums(val_record_file)print('train nums:%d,val nums:%d'%(train_nums,val_nums))# 從record中讀取圖片和labels數據# train數據,訓練數據一般要求打亂順序shuffle=Truetrain_images, train_labels = read_records(train_record_file, resize_height, resize_width, type='normalization')train_images_batch, train_labels_batch = get_batch_images(train_images, train_labels,batch_size=batch_size, labels_nums=labels_nums,one_hot=True, shuffle=True)# val數據,驗證數據可以不需要打亂數據val_images, val_labels = read_records(val_record_file, resize_height, resize_width, type='normalization')val_images_batch, val_labels_batch = get_batch_images(val_images, val_labels,batch_size=batch_size, labels_nums=labels_nums,one_hot=True, shuffle=False)# Define the model:with slim.arg_scope(mobilenet_v1.mobilenet_v1_arg_scope()):out, end_points = mobilenet_v1.mobilenet_v1(inputs=input_images, num_classes=labels_nums,dropout_keep_prob=keep_prob, is_training=is_training,global_pool=True)# Specify the loss function: tf.losses定義的loss函數都會自動添加到loss函數,不需要add_loss()了tf.losses.softmax_cross_entropy(onehot_labels=input_labels, logits=out) # 添加交叉熵損失loss=1.6# slim.losses.add_loss(my_loss)loss = tf.losses.get_total_loss(add_regularization_losses=True) # 添加正則化損失loss=2.2# Specify the optimization scheme:# 在定義訓練的時候, 注意到我們使用了`batch_norm`層時,需要更新每一層的`average`和`variance`參數,# 更新的過程不包含在正常的訓練過程中, 需要我們去手動像下面這樣更新# 通過`tf.get_collection`獲得所有需要更新的`op`update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)# 使用`tensorflow`的控制流, 先執行更新算子, 再執行訓練with tf.control_dependencies(update_ops):print("update_ops:{}".format(update_ops))# create_train_op that ensures that when we evaluate it to get the loss,# the update_ops are done and the gradient updates are computed.# train_op = tf.train.MomentumOptimizer(learning_rate=base_lr, momentum=0.9).minimize(loss)train_op = tf.train.AdadeltaOptimizer(learning_rate=base_lr).minimize(loss)accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(out, 1), tf.argmax(input_labels, 1)), tf.float32))# 循環迭代過程step_train(train_op=train_op, loss=loss, accuracy=accuracy,train_images_batch=train_images_batch,train_labels_batch=train_labels_batch,train_nums=train_nums,train_log_step=train_log_step,val_images_batch=val_images_batch,val_labels_batch=val_labels_batch,val_nums=val_nums,val_log_step=val_log_step,snapshot_prefix=snapshot_prefix,snapshot=snapshot)if __name__ == '__main__':train_record_file='dataset/record/train224.tfrecords'val_record_file='dataset/record/val224.tfrecords'train_log_step=100base_lr = 0.001 # 學習率# 重頭開始訓練的話,mobilenet收斂慢的一比,大概20000次迭代后,準確率開始蹭蹭的往上長,迭代十萬次后準確率才70%max_steps = 100000 # 迭代次數train_param=[base_lr,max_steps]val_log_step=500snapshot=2000#保存文件間隔snapshot_prefix='models/model.ckpt'train(train_record_file=train_record_file,train_log_step=train_log_step,train_param=train_param,val_record_file=val_record_file,val_log_step=val_log_step,labels_nums=labels_nums,data_shape=data_shape,snapshot=snapshot,snapshot_prefix=snapshot_prefix)

    7、模型預測

    模型預測,項目只提供一個predict.py,實質上,你只需要稍微改改,就可以預測其他模型

    #coding=utf-8import tensorflow as tf import numpy as np import pdb import cv2 import os import glob import slim.nets.inception_v3 as inception_v3from create_tf_record import * import tensorflow.contrib.slim as slimdef predict(models_path,image_dir,labels_filename,labels_nums, data_format):[batch_size, resize_height, resize_width, depths] = data_formatlabels = np.loadtxt(labels_filename, str, delimiter='\t')input_images = tf.placeholder(dtype=tf.float32, shape=[None, resize_height, resize_width, depths], name='input')#其他模型預測請修改這里with slim.arg_scope(inception_v3.inception_v3_arg_scope()):out, end_points = inception_v3.inception_v3(inputs=input_images, num_classes=labels_nums, dropout_keep_prob=1.0, is_training=False)# 將輸出結果進行softmax分布,再求最大概率所屬類別score = tf.nn.softmax(out,name='pre')class_id = tf.argmax(score, 1)sess = tf.InteractiveSession()sess.run(tf.global_variables_initializer())saver = tf.train.Saver()saver.restore(sess, models_path)images_list=glob.glob(os.path.join(image_dir,'*.jpg'))for image_path in images_list:im=read_image(image_path,resize_height,resize_width,normalization=True)im=im[np.newaxis,:]#pred = sess.run(f_cls, feed_dict={x:im, keep_prob:1.0})pre_score,pre_label = sess.run([score,class_id], feed_dict={input_images:im})max_score=pre_score[0,pre_label]print("{} is: pre labels:{},name:{} score: {}".format(image_path,pre_label,labels[pre_label], max_score))sess.close()if __name__ == '__main__':class_nums=5image_dir='test_image'labels_filename='dataset/label.txt'models_path='models/model.ckpt-10000'batch_size = 1 #resize_height = 299 # 指定存儲圖片高度resize_width = 299 # 指定存儲圖片寬度depths=3data_format=[batch_size,resize_height,resize_width,depths]predict(models_path,image_dir, labels_filename, class_nums, data_format)

    8、其他模型訓練方法?

    ? ? 上面的程序是訓練MobileNet的完整過程,實質上,稍微改改就可以支持訓練 inception V1,V2和resnet?啦,改動方法也很簡單,以 MobileNe訓練代碼改為resnet_v1模型為例:

    (1)import 改為:

    # 將 import slim.nets.mobilenet_v1 as mobilenet_v1 # 改為 import slim.nets.resnet_v1 as resnet_v1

    (2)record數據

    ?制作record數據時,需要根據模型輸入設置:

    resize_height = 224 ?# 指定存儲圖片高度
    resize_width = 224 ?# 指定存儲圖片寬度

    (3)定義模型和默認參數修改:

    # 將# Define the model:with slim.arg_scope(mobilenet_v1.mobilenet_v1_arg_scope()):out, end_points = mobilenet_v1.mobilenet_v1(inputs=input_images, num_classes=labels_nums,dropout_keep_prob=keep_prob, is_training=is_training,global_pool=True)# 改為# Define the model:with slim.arg_scope(resnet_v1.resnet_arg_scope()):out, end_points = resnet_v1.resnet_v1_101(inputs=input_images, num_classes=labels_nums, is_training=is_training,global_pool=True)

    (4)修改優化方案

    對于大型的網絡模型,重頭開始訓練,是很難收斂的。訓練mobilenet時,在迭代10000次以前,loss和準確率幾乎不會提高。一開始我以為是訓練代碼寫錯了,后來尋思了很久,才發現是模型太復雜了,所以收斂慢的一比,大概20000次迭代后,準確率才開始蹭蹭的往上長,迭代十萬次后準確率才70%,若訓練過程發現不收斂,請嘗試修改:

    1、等!!!!至少你要迭代50000次,才能說你的模型不收斂!

    2、增大或減小學習率參數:base_lr(個人經驗:模型越深越復雜時,學習率越小)

    3、改變優化方案:如使用MomentumOptimizer或者AdadeltaOptimizer等優化方法

    4、是否有設置默認的模型參數:如slim.arg_scope(inception_v1.inception_v1_arg_scope())

    ……最后,就可以Train了!是的,就是那么簡單~

    總結

    以上是生活随笔為你收集整理的使用自己的数据集训练MobileNet、ResNet实现图像分类(TensorFlow)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。