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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Fine-turning(Tensorflow-Slim和Keras的迁移学习)

發(fā)布時(shí)間:2024/1/18 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Fine-turning(Tensorflow-Slim和Keras的迁移学习) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


遷移學(xué)習(xí)是什么?
即:舉一反三。即將已經(jīng)訓(xùn)練好的模型稍加調(diào)整(fine-turning)即可應(yīng)用于一個(gè)新的領(lǐng)域或者任務(wù)。主要流程如上圖。

遷移學(xué)習(xí)為什么重要?

  • 機(jī)器學(xué)習(xí)的默認(rèn)假設(shè),訓(xùn)練樣本和測(cè)試樣本滿足獨(dú)立同分布的前提是訓(xùn)練樣本足夠。
  • 數(shù)據(jù)的稀缺性。如在想要做醫(yī)學(xué)領(lǐng)域的圖像處理,所能得到的樣本是極端的不平衡,重要的樣本太少,無(wú)法訓(xùn)練出一個(gè)效果好的網(wǎng)絡(luò)。
  • 標(biāo)記的困難性。大數(shù)據(jù)時(shí)代動(dòng)輒億萬(wàn)數(shù)據(jù),標(biāo)記起來(lái)太費(fèi)時(shí)費(fèi)力。(題外話,半標(biāo)簽問(wèn)題可以使用偽標(biāo)簽技術(shù),即將test的數(shù)據(jù)加到train數(shù)據(jù)集中,其對(duì)應(yīng)的標(biāo)簽為原數(shù)據(jù)集訓(xùn)練得到的。這種方法具有一定的泛化增強(qiáng)能力,最好是在網(wǎng)絡(luò)迭代幾輪后再將已有標(biāo)簽和無(wú)標(biāo)簽一起訓(xùn)練。一般會(huì)在batch有1/4-1/3的偽標(biāo)簽數(shù)據(jù)。)
  • 框架太難訓(xùn)練。想要得到復(fù)雜有效的框架都需要長(zhǎng)時(shí)間的訓(xùn)練,設(shè)備、時(shí)間、人力都成問(wèn)題。
  • 任務(wù)的擴(kuò)展性。在實(shí)際中如果有些應(yīng)用需要添加新的模塊,或者收集到的數(shù)據(jù)發(fā)生了變化,那么重新訓(xùn)練一次?沒(méi)有更輕松快捷的方法嗎?

在前一篇文章–目標(biāo)檢測(cè)中,就使用過(guò)Tensorflow Object Detection API里面所自帶的模型訓(xùn)練了自己的數(shù)據(jù)集。這篇再整理用TF-slim和keras完成任務(wù)。

TF-slim
它是TensorFlow(tensorflow.contrib.slim)的一個(gè)輕量級(jí)高級(jí)API,用于定義,訓(xùn)練和評(píng)估復(fù)雜模型。包含常用的網(wǎng)絡(luò)架構(gòu)模型如VGG, AlexNet,可以讓從頭開(kāi)始訓(xùn)練模型,也可以利用預(yù)先訓(xùn)練好的網(wǎng)絡(luò)權(quán)重對(duì)其進(jìn)行微調(diào)(fine-turn)。

安裝:
python -c "import tensorflow.contrib.slim as slim; eval = slim.evaluation.evaluate_once"

但是它的出現(xiàn)本身其實(shí)是為了–代碼瘦身,即在不用keras,tensorlayer,tflearn這些高級(jí)庫(kù)的條件下就可以寫出簡(jiǎn)單優(yōu)美的代碼。如定義變量它的寫法是:

# Model Variables weights = slim.model_variable('weights',shape=[10, 10, 3 , 3],initializer=tf.truncated_normal_initializer(stddev=0.1),regularizer=slim.l2_regularizer(0.05),device='/CPU:0') model_variables = slim.get_model_variables()#返回模型變量# Regular variables my_var = slim.variable('my_var',shape=[20, 1],initializer=tf.zeros_initializer())regular_variables_and_model_variables = slim.get_variables()#返回所有變量,包括局部變量

定義網(wǎng)絡(luò)層則是一行代碼:

net1 = slim.conv2d(input, 128, [3, 3], scope='conv1') net2 = slim.repeat(net1, 3, slim.conv2d, 256, [3, 3], scope='conv3')#repeat可以直接搭3個(gè)卷積層 net3 = slim.max_pool2d(net2, [2, 2], scope='pool2')#stack和repert是不同是,它可以處理卷積核或者全連接層輸出不一樣的情況 slim.stack(x, slim.conv2d, [(32, [3, 3]), (32, [1, 1]), (64, [3, 3]), (64, [1, 1])], scope='core') slim.stack(x, slim.fully_connected, [32, 64, 128], scope='fc')

用arg_scope來(lái)完成參數(shù)共享,整個(gè)VGG都十分輕松:

def vgg16(inputs):with slim.arg_scope([slim.conv2d, slim.fully_connected],activation_fn=tf.nn.relu,weights_initializer=tf.truncated_normal_initializer(0.0, 0.01),weights_regularizer=slim.l2_regularizer(0.0005)):#共享的參數(shù)寫到一起net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1')#其他的單獨(dú)再搭net = slim.max_pool2d(net, [2, 2], scope='pool1')net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2')net = slim.max_pool2d(net, [2, 2], scope='pool2')net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')net = slim.max_pool2d(net, [2, 2], scope='pool3')net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv4')net = slim.max_pool2d(net, [2, 2], scope='pool4')net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv5')net = slim.max_pool2d(net, [2, 2], scope='pool5')net = slim.fully_connected(net, 4096, scope='fc6')net = slim.dropout(net, 0.5, scope='dropout6')net = slim.fully_connected(net, 4096, scope='fc7')net = slim.dropout(net, 0.5, scope='dropout7')net = slim.fully_connected(net, 1000, activation_fn=None, scope='fc8')return net

不過(guò)不需要,slim里面有已經(jīng)訓(xùn)練完成了的模型,可以直接用來(lái)預(yù)測(cè)。完整的tf-slim使用手冊(cè):https://github.com/tensorflow/models/blob/master/research/slim/slim_walkthrough.ipynb

import tensorflow as tf vgg = tf.contrib.slim.nets.vgg#vgg模型images, labels = ...#載入圖像和標(biāo)簽 predictions, _ = vgg.vgg_16(images)#預(yù)測(cè) loss = slim.losses.softmax_cross_entropy(predictions, labels)#損失函數(shù)


fine-turn新模型
以下都是基于inception進(jìn)行微調(diào),inception是一個(gè)組合的卷積核,能夠讓網(wǎng)絡(luò)進(jìn)行自行選擇,同時(shí)又加入了1X1的卷積減少參數(shù)。對(duì)它進(jìn)行微調(diào)可以理解為是把前面的卷積層一起當(dāng)成一個(gè)特征提取器,將后面的全卷積換成掉訓(xùn)練新的數(shù)據(jù)集如下圖(畢竟新的數(shù)據(jù)集無(wú)論從種類數(shù)量等等都還是不一樣的),便可以使它完成新的任務(wù)(比如可以拿普通的圖像識(shí)別網(wǎng)絡(luò)在數(shù)據(jù)少的醫(yī)學(xué)圖像上進(jìn)行遷移學(xué)習(xí))。所以操作時(shí)往往先會(huì)凍結(jié)前面卷積的權(quán)重,只需要fine-turn后面的參數(shù)就可以了。當(dāng)然可以基于它的權(quán)重進(jìn)行全網(wǎng)絡(luò)的微調(diào)。

先下載tf-slim完整的圖像模型庫(kù):
git clone https://github.com/tensorflow/models/

由于Tensorflow的訓(xùn)練集需要是tfrecord模式,如果使用現(xiàn)成的數(shù)據(jù)集ImageNet等就不需要轉(zhuǎn)換,如果是自己的數(shù)據(jù)集需要先做處理。如有一個(gè)叫A的數(shù)據(jù)集,通過(guò)下來(lái)命令使用 download_and_convert_data.py可以轉(zhuǎn)換。

$ DATA_DIR=/tmp/data/A $ python download_and_convert_data.py \--dataset_name=flowers \--dataset_dir="${DATA_DIR}"

由于slim本身有MNIST,CIFAR-10 ,Flowers ,ImageNet數(shù)據(jù)集,如果要加入自己的數(shù)據(jù),需要在數(shù)據(jù)集datasets里面注冊(cè)一下。便可以導(dǎo)入了。

import tensorflow as tf from datasets import A slim = tf.contrib.slimdataset = A.get_split('validation', DATA_DIR) provider = slim.dataset_data_provider.DatasetDataProvider(dataset) [image, label] = provider.get(['image', 'label'])

下載模型并解壓,比如inception_v3

$ CHECKPOINT_DIR=/tmp/checkpoints $ mkdir ${CHECKPOINT_DIR} $ wget http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz $ tar -xvf inception_v3_2016_08_28.tar.gz $ mv inception_v3.ckpt ${CHECKPOINT_DIR} $ rm inception_v3_2016_08_28.tar.gz

然后開(kāi)始fine-turn。其中–checkpoint_exclude_scopes會(huì)阻止某些變量被加載。當(dāng)使用與訓(xùn)練模型不同數(shù)量的分類任務(wù)進(jìn)行微調(diào)時(shí),新模型將具有最終的“分類”層,其尺寸與預(yù)先訓(xùn)練的模型不同。標(biāo)志–checkpoint_path和–checkpoint_exclude_scopes期間僅用于模型初始化。通常情況下,微調(diào)只需要訓(xùn)練一組子層,因此該標(biāo)志–trainable_scopes允許指定層的哪些子層應(yīng)該訓(xùn)練,其余的將保持凍結(jié)。

$ python train_image_classifier.py \--train_dir=${TRAIN_DIR} \--dataset_dir=${DATASET_DIR} \--dataset_name=A \ #訓(xùn)練數(shù)據(jù)集--dataset_split_name=train \--model_name=inception_v3 \--checkpoint_path=${CHECKPOINT_PATH} \--checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits \ #調(diào)參范圍,只對(duì)輸出層做調(diào)整--trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits #若不設(shè)定此項(xiàng),將全參數(shù)調(diào)整--max_number_of _steps=10000 \ #其他的學(xué)習(xí)參數(shù)控制--batch size=64 \ --learning_rate=0.001 \ --learning_rate_decay_type=fixed \ #學(xué)習(xí)率是否遞減--save_interval secs=300 \ #保存模型的時(shí)間間隔--save_summaries_secs=2 \ 用tensorboard的更新時(shí)間--log_every_n_steps=10 \ #打印信息的步長(zhǎng)間隔--optimizer=rmsprop \--weight_decay=0.00001 #正則化參數(shù)

tensorboard --logdir=${TRAIN_DIR}查看訓(xùn)練情況。
測(cè)試性能:

CHECKPOINT_FILE = ${CHECKPOINT_DIR}/inception_v3.ckpt $ python eval_image_classifier.py \--alsologtostderr \--checkpoint_path=${CHECKPOINT_FILE} \--dataset_dir=${DATASET_DIR} \--dataset_name=A \--dataset_split_name=validation \--model_name=inception_v3

TF-slim代碼實(shí)現(xiàn)fine-turn
不采用上面的命令方法可以通過(guò)代碼的方式完成:

import osfrom datasets import flowers#使用它自己的flowers,如果是A同樣需要設(shè)置一下 from nets import inception from preprocessing import inception_preprocessingfrom tensorflow.contrib import slim image_size = inception.inception_v1.default_image_size#得到原網(wǎng)絡(luò)權(quán)重 def get_init_fn(): #前面提過(guò)的checkpoint_exclude_scopes確定fine-turn范圍checkpoint_exclude_scopes=["InceptionV1/Logits", "InceptionV1/AuxLogits"]exclusions = [scope.strip() for scope in checkpoint_exclude_scopes]variables_to_restore = []for var in slim.get_model_variables():for exclusion in exclusions:if var.op.name.startswith(exclusion):breakelse:variables_to_restore.append(var)return slim.assign_from_checkpoint_fn(os.path.join(checkpoints_dir, 'inception_v1.ckpt'),variables_to_restore)#訓(xùn)練集 train_dir = '/tmp/inception_finetuned/'with tf.Graph().as_default():tf.logging.set_verbosity(tf.logging.INFO)#日志dataset = flowers.get_split('train', flowers_data_dir)#切分?jǐn)?shù)據(jù)images, _, labels = load_batch(dataset, height=image_size, width=image_size)# 創(chuàng)建模型,使用默認(rèn)的參數(shù)范圍配置參數(shù)。with slim.arg_scope(inception.inception_v1_arg_scope()):logits, _ = inception.inception_v1(images, num_classes=dataset.num_classes, is_training=True)#損失函數(shù)one_hot_labels = slim.one_hot_encoding(labels, dataset.num_classes)slim.losses.softmax_cross_entropy(logits, one_hot_labels)total_loss = slim.losses.get_total_loss()tf.summary.scalar('losses/Total Loss', total_loss)#便于顯示optimizer = tf.train.AdamOptimizer(learning_rate=0.01)#優(yōu)化器train_op = slim.learning.create_train_op(total_loss, optimizer)#開(kāi)始訓(xùn)練final_loss = slim.learning.train(train_op,logdir=train_dir,init_fn=get_init_fn(),number_of_steps=2)print('Finished training. Last batch loss %f' % final_loss)

用keras進(jìn)行fine-turn

from keras.applications.inception_v3 import InceptionV3 #同樣載入v3 from keras.preprocessing import image from keras.models import Model from keras.layers import Dense, GlobalAveragePooling2D from keras.preprocessing.image import ImageDataGenerator from keras import backend as K import os import tensorflow as tf os.environ["CUDA_VISIBLE_DEVICES"] = "6" gpu_options = tf.GPUOptions(allow_growth=True) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) from keras.utils import plot_model from matplotlib import pyplot as plt#InceptionV3模型,加載預(yù)訓(xùn)練權(quán)重,但是不保留最后的三個(gè)全連接層,進(jìn)行微調(diào) base_model = InceptionV3(weights='imagenet', include_top=False) print(base_model.summary()) # summary便于顯示 plot_model(base_model,to_file = 'InceptionV3.png') # 保存模型結(jié)構(gòu)圖x = base_model.output x = GlobalAveragePooling2D()(x)#全局平均池化層x = Dense(1024, activation='relu')(x) predictions = Dense(2, activation='softmax')(x)#增加兩個(gè)全連接層model = Model(inputs=base_model.input, outputs=predictions)#模型合并,得到新模型 print(base_model.summary()) plot_model(model,to_file = 'InceptionV3.png') for layer in base_model.layers:layer.trainable = False #凍結(jié)層model.compile(optimizer='rmsprop', loss='categorical_crossentropy')#開(kāi)始編譯#生成訓(xùn)練數(shù)據(jù) train_datagen = ImageDataGenerator(rescale=1./255,shear_range=0.2,zoom_range=0.2,horizontal_flip=True)train_generator = train_datagen.flow_from_directory('.train/', target_size=(150, 150), batch_size=32,class_mode='categorical') #開(kāi)始測(cè)試 test_datagen = ImageDataGenerator(rescale=1./255)validation_generator = test_datagen.flow_from_directory('./validation/',target_size=(150, 150),batch_size=32,class_mode='categorical')#新數(shù)據(jù)開(kāi)始訓(xùn)練 model.fit_generator(train_generator,steps_per_epoch=2000,epochs=1,validation_data=validation_generator,validation_steps=800)#凍結(jié)部分層,然后訓(xùn)練其他層 for i, layer in enumerate(base_model.layers): # 打印出每次的名字print(i, layer.name)for layer in model.layers[:249]:layer.trainable = False for layer in model.layers[249:]:layer.trainable = True#重新訓(xùn)練 from keras.optimizers import SGD model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy')model.fit_generator(train_generator,steps_per_epoch=2000,epochs=1,validation_data=validation_generator,validation_steps=800)

fine-turning效果如何?
一圖勝千言。

fune-turning技巧

  • 只替掉最后一層,改成本任務(wù)的類別
  • 替到最后一層,freeze backbone到收斂,再開(kāi)放所有層一起
  • 替到最后一層,用差分學(xué)習(xí)率(discriminative learning)即backbone和最后一層學(xué)習(xí)率不一樣,畢竟backbone已經(jīng)很好了可以選用比如10倍
  • 替到最后一層,freeze淺層,訓(xùn)練深層,以增強(qiáng)泛化,減少過(guò)擬合
  • 好的學(xué)習(xí)率(如3e-4是Adam最好學(xué)習(xí)率)

總結(jié)

以上是生活随笔為你收集整理的Fine-turning(Tensorflow-Slim和Keras的迁移学习)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。