圖片標(biāo)注問題image_caption

數(shù)據(jù)集:

  • 數(shù)據(jù)集中的訓(xùn)練集使用的是coco train 2014,82783張圖片,測試集使用的是 val 2017 ,5000張圖片,對應(yīng)的caption是captions_train2014.json,和captions_val2017.json。
    該文件中是以字典的形式包含其內(nèi)容信息,key值由“info”,”licenses“,”images“,”annotations“組成。
    info:其中包括數(shù)據(jù)集建立的時間。下載地址,版本號等。
    licenses:是數(shù)據(jù)集使用條款。
    images:包括圖片的filename,height,width ,圖片對應(yīng)的網(wǎng)址,圖片對應(yīng)的caption的id。
    annotation:包含image_id,對應(yīng)的caption的id,和每個圖片對應(yīng)的5句描述

  • 訓(xùn)練:

    訓(xùn)練集使用的是coco train 2014中的全部數(shù)據(jù)。

  • 測試:

    測試集使用的是coco val 2017中的的數(shù)據(jù)。

  • 數(shù)據(jù)預(yù)處理:

    build_data.py中定義了以下幾個函數(shù):

  1.def load_and_process_metadata(captions_file,image_dir): 
         with open(captions_file, encoding='utf-8') as f:
         lines = f.readline()
         d = json.loads(lines)
         print(d)
         f.close()
                

d["images"]

d["images"]中包含的內(nèi)容

[{'license':6,'file_name':'000000492110.jpg','coco_url':'http://images.cocodataset.org/val2017/000000492110.jpg', 'height': 427, 'width': 640, 'date_captured': '2013-11-24 00:43:28', 'flickr_url': 'http://farm9.staticflickr.com/8195/8139005828_fda85b4b72_z.jpg', 'id': 492110}]

d["annotations"]中包含的內(nèi)容

[{'image_id': 54592, 'id': 562033, 'caption': 'Couple of people walking up the snowy mountain with skis'},
{'image_id': 23034, 'id': 561930, 'caption': 'A man smiles watching a rider approach with two horses.'}]

captions_file:caption_train2014.json和val_2014.json文件的路徑。
image_dir:train_2014和val_2014的路徑。
函數(shù)作用:
讀取json文件將image和對應(yīng)的caption對應(yīng),將內(nèi)容封裝到 ImageMetadata中,這時的一個image_id對應(yīng)一個filename對應(yīng)五個captions

效果
COCO_train2014_000000458922.jpg
描述captions
'Beef and other food on a plate next to a wine glass',
'A finished steak dinner and glass of wine are on a table.',
'some food and a fork is on a plate',
'A plate with fork and steak and a wine glass on placemat with papers in background.',
'a rare steak with a fork and a glass of wine
COCO_train2014_000000058245.jpg
圖片描述captions
'A blue vase filled with colorful flowers sitting on the ground.',
'A blue vase on table holding red flowers next to door.',
'A bunch of orange flowers in a blue vase on a runner on a table.',
'A blue glass vase with some flowers on a table.',
'A blue glass vase with red and yellow flowers

namedtuple("ImageMetadata",["image_id","filename",'captions']

1.讀取json文件使用json中的json.loads()方法。
2.索取json中的信息就直接使用字典中的方法就好。

      2.def process_caption(caption):
              tokenized_caption=[FLAGS.start_word]
              tokenized_caption.extend(nltk.tokenize.word_tokenize(caption.lower()))
              tokenized_caption.extend(FLAGS.end_word)

函數(shù)作用:將”start_word“和”end_word“加載到每句話中的開始和結(jié)束,作用類似于起始密碼子,終止密碼子,蛋白質(zhì)合成的起始,和終止。并把caption變成小寫,目的不讓同一個單詞在vocabulary字典中出現(xiàn)兩次節(jié)省資源。
1.使用方法是用列表中的entend方法

     3.def create_vocab(captions):
             counter = Counter()
             for c in captions:
                  counter.update(c)
             word_counts = [x for x in counter.items() if x[1] >= 4]
             word_counts.sort(key=lambda x: x[1], reverse=True)

函數(shù)作用:統(tǒng)計caption中的所有單詞,和出現(xiàn)的頻率,并把單詞以及單詞出現(xiàn)的頻率
寫入到txt文件中。
1.使用到的方法有collections 中 Counter,Counter是一個計數(shù)器,將單詞輸入其中可
直接將單詞的出現(xiàn)頻率顯示出來。并將重復(fù)的單詞去除。并只取單詞中頻率大于4的。并從小到大排序。然后創(chuàng)建一個字典將排序好的單詞取出,將單詞從0~vocab_size給單詞賦一個id。

 4.class Vocabulary(object):
      def __init__(self, vocab, unk_id):

vocab:是單詞帶有對應(yīng)id的字典。
unk_id:是對應(yīng)vocab_size,也就是單詞的長度,如果單詞沒在制作的dict中就返回
一個空的字符。

word_to_id(self, word):

給定caption中的單詞,如果單詞在dict中返回對應(yīng)的word_id,不在就返回unk_id。

5. def process_dataset()

函數(shù)作用:這時的一個image仍然是對應(yīng)一個caption。將image遍歷,使每一個image對應(yīng)一個caption。然后將caption,和image讀入tfrecord中。

images = [ImageMetadata(image.image_id, image.filename, [caption])
for image in images for caption in image.captions]
random.seed(12345)
random.shuffle(images)

使用random的方法將image_caption的順序打亂。

  • tfrecord的使用方法

定義寫入tfrecord文件地writer
writer=tf.python_io.TFRecordwriter(filename) # filename:tfrecord保存的地址
文件名隊列在上述的images中已經(jīng)構(gòu)造好了
for i in range(len(images))
image=images[i]:
獲取每個image對應(yīng)的圖片地址+文件名
image_filename=image.filename
獲取每句image的描述
caption=image.captions
獲得每句caption的id
caption_id=word_to_id(caption)

  • 讀入image,并解碼

    with tf.gfile.FastGFile(image.filename, "rb") as f:
    encoded_image = f.read()

解碼:
1. tf.decode_csv() 解碼文件文本內(nèi)容
2.tf.image.decode_jpeg(countent) 將jpeg編碼的圖像解碼為uint8張量
3.tf.image.decode_png(content) 將png編碼的圖像解碼為uint8張量
4.tf.decode_raw(value,uint8)解碼二進制內(nèi)容

構(gòu)造example:

def _int64_feature(value):
  """將int 64特性插入序列中的包裝器"""
  return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def _bytes_feature(value):
  """將字節(jié)特性插入序列示例Proto的包裝器"""
  value = tf.compat.as_bytes(value)
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature_list(values):
  """將int 64 FeatureList插入序列的包裝器-示例Proto"""
  return tf.train.FeatureList(feature=[_int64_feature(v) for v in values])
def _bytes_feature_list(values):
  """將字節(jié)FeatureList插入序列示例Proto的包裝器"""
  return tf.train.FeatureList(feature=[_bytes_feature(v) for v in values])
 context = tf.train.Features(feature={     
      "image/image_id":_int64_feature(image.image_id),
      "image/data": _bytes_feature(encoded_image),
  })
feature_lists = tf.train.FeatureLists(feature_list={
      "image/caption": _bytes_feature_list(caption),
      "image/caption_ids": _int64_feature_list(caption_ids)
  })

那么什么樣的數(shù)據(jù)需要映射為FeatureList或Feature?
我的理解是數(shù)字表示,二分類就是0或1,那么就class=0映射為tf.train.Feature(tf.train.Int64List(value=[0])), 只要這個字段包含的數(shù)據(jù)維度是固定的,就可以封裝為 Feature。
對于長度不固定的字段類型,映射為FeatureList。比如NLP樣本有一個特征是一句話,那么一句話的長度是不固定的,NLP中一般是先分詞,然后把每個詞對應(yīng)為該詞在字典中的索引,一句話就用一個一維整形數(shù)組來表示 [2, 3, 5, 20, ...],這個數(shù)組的長度是不固定的,我們就映射為
這里將caption通過上述的函數(shù)word_to_id中將caption轉(zhuǎn)化為caption_id。
sequence_example = tf.train.SequenceExample(
context=context, feature_lists=feature_lists)

將caption的feature和images的feature保存到tf.train.SequenceExample中,
將序列化后的example寫入文件

wtiter.write(example.SerializeToString())
write.close()

讀取tfrecord
  • 構(gòu)造文件名讀取隊列

1.將需要讀取的文件名放入到文件名隊列中

tf.train.string_input_producer(data_file,shuffle=True)
data_file:tfrecord的文件名
shuffle=True:默認文件名隨機打亂

  • 讀取

使用TFRecorder的方法讀入
_,serialized_example=reader.read(filename_queue)

  • 解析example
context, sequence = tf.parse_single_sequence_example(example_serialized,
                    context_features={
                        image_feature: tf.FixedLenFeature([], dtype=tf.string)},
                    sequence_features={
                        caption_feature: tf.FixedLenSequenceFeature([], dtype=tf.int64) })
self.encoded_image = context[image_feature]
self.caption = sequence[caption_feature]
  • 解碼

解碼仍然使用上述中的解碼方法
tf.image.decode_jpeg(self.encoded_image)
使用tf.cast()方法將其轉(zhuǎn)換為tf.float32,由于每張圖片的大小可能不是統(tǒng)一大小的,為了方便后面的cnn提取特征,將圖片統(tǒng)一大小。使用tf.image.resize_images(image,size=[])

在圖片處理時將圖片進行數(shù)據(jù)歸一化,優(yōu)點是
1.歸一化后加快梯度下降求最優(yōu)解的速度
2.歸一化后有可能提高精度
3.使用梯度法求最優(yōu)解時,歸一化往往非常有必要,否則模型很難收斂,甚至不能收斂

方法1
image = tf.image.convert_image_dtype(image, dtype=tf.float32) # 將圖片像素值變?yōu)閇0,1]
image = tf.subtract(image, 0.5) # 圖片像素值域由[0, 1]變換為[-0.5,0.5]
image = tf.multiply(image, 2.0) # 圖片像素值域由[0,0.5]變?yōu)閇-1,1]

方法2
def image_to_float(image)
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
return (image/127.5) - 1.0

方法3
在人臉識別中用到的直接將特征值除以255的簡單縮放法

圖片處理

在對圖片處理時要進行以下操作,目的是為了防止過擬合,過擬合是指我們訓(xùn)練的模型“實在是太好了”對與訓(xùn)練的數(shù)據(jù)分類預(yù)測效果都特別好,而面對新的數(shù)據(jù)時變現(xiàn)的效果可能就沒那么好了。我們訓(xùn)練數(shù)據(jù)的目的是讓模型既不過擬合,也不是欠擬合,而是處于過擬合與欠擬合之間的一種狀態(tài)。欠擬合是指無論是對于測試集還是訓(xùn)練集的效果,表現(xiàn)得都不是很好。就比如我們復(fù)習(xí)數(shù)學(xué)吧,我們只把課本上的題會做理解,而考試面對新的題,可能只是修改個數(shù)我們就做的不太好,這種狀態(tài)稱為過擬合。而我們連書的內(nèi)容看都不看的話,啥題都不會的情況就是欠擬合。

 image = tf.image.random_flip_left_right(image)
調(diào)整圖片的隨機亮度
image = tf.image.random_brightness(image, max_delta=32 / 255)
 調(diào)整圖片飽和度
 image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
 隨機調(diào)整RGB圖像的色調(diào)
 image = tf.image.random_hue(image, max_delta=0.032)
 在某范圍隨機調(diào)整圖片對比度
image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
輸入一個張量image,把image中的每一個元素的值都壓縮在min和max之間。小于min的讓它等于min,大于max的元素值等于max
image = tf.clip_by_value(image, 0, 1.0)
  • 對caption構(gòu)造input_sequence,target_sequence
       images_and_captions = []
       images_and_captions.append([image, self.caption])
       enqueue_list = []
        for image, caption in images_and_captions:
            # 獲取每個句子的長度
            caption_length = tf.shape(caption)[0]
            # 將句子id向后移動一
            input_length = tf.expand_dims(tf.subtract(caption_length, 1), 0)
            # 真正句子的id
            input_seq = tf.slice(caption, [0], input_length)
            # 句子向有移動后的句子id目的是為了預(yù)測下一個單詞
            target_seq = tf.slice(caption, [1], input_length)
            indicator = tf.ones(input_length, dtype=tf.int32)
            enqueue_list.append([image, input_seq, target_seq, indicator])
  • 構(gòu)造批出理隊列

有兩種方法:tf.train.batch和tf.train.batch_join的區(qū)別,一般來說,單一文件多線程,那么選用tf.train.batch(需要打亂樣本,有對應(yīng)的tf.train.shuffle_batch);而對于多線程多文件的情況,一般選用tf.train.batch_join來獲取樣本(打亂樣本同樣也有對應(yīng)的tf.train.shuffle_batch_join使用)。

第一種
tf.train.batch_join(enqueue_list,
            batch_size=self.batch_size,
            capacity=queue_capacity,
            dynamic_pad=True,
            name="batch_and_pad"))
第二種
tf.train.batch(enquene_list,
                    batch=self.batch_size,
                    capacity=queue_capacity,
                    name="batch_and_pad") 
  • 構(gòu)造image_embedding
    將解碼后的圖片經(jīng)過CNN的全連接層后生成[batch_size,512]的向量
  • 構(gòu)造caption_embedding

將輸入的seq變成詞向量,詞向量才能在lstm中進行訓(xùn)練計算

原理就是
image.png

這里假設(shè)詞表中有“我,愛,河,南,科,技”6個字,在類比one-hot編碼的時候就形成了一個[6,6]的矩陣emdedding-map,然后我如果想取出其中的兩個單詞“河”,“南”那么就需要查emdedding-map。進行類似的矩陣相乘得到兩個詞的詞向量。

embedding_map=tf.get_variable(name="map",shape[vocab_size,512],initializer=self.initializer)
seq_embeddings = tf.nn.embedding_lookup(embedding_map, self.input_seqs)
返回的是tensor 的 shape是 [batch_size,word_size,512]

模型:

1.結(jié)構(gòu)

  • CNN

1,cnn使用的是inceptionv3模型:主要提取圖片的特征,
inceptionv3具有很少的參數(shù)量,節(jié)省計算時間加快學(xué)習(xí)速度;5x5的卷積核用兩個3x3的 卷積核代替增強表達能力,為減少計算復(fù)雜度將卷積轉(zhuǎn)化為稀疏連接以下展示cnn的結(jié)構(gòu)圖;


7D7A837EF287B16474B652BF3EE657EA.jpg

290284015DEB91BC4B9006A7E4D66F5C.jpg

225EBB66053EF93D5E7263B64BA6319E.jpg
10EEDBD008D7BD87A4846F2F3BC0CA54.jpg
35642BE60F475B4592BE6A50E809DB3C.jpg
2.模型輸入的image尺寸為299x299X3 ,batch_size=32 數(shù)據(jù)類型為float32

shape:[batch_size, height, width, channels]

4.使用batch_normalization.(簡稱BN)

BN是一種解決深度神經(jīng)網(wǎng)絡(luò)層數(shù)太多,而沒有辦法有效向前傳遞的問題,因為每一層的輸出值都會有不同的均值,和方差,所以輸出的數(shù)據(jù)分布也不一樣。
優(yōu)點:
1.他不僅加快模型的收斂速度,而且更重要的是在一定程度上緩解了深度網(wǎng)絡(luò)中的“梯度彌散”(就是在靠近輸出層的hidden layer梯度越大,參數(shù)更新快,但是靠近輸入層的hidden layer梯度小,參數(shù)更新慢,幾乎和初始狀態(tài)一樣,隨機分布。梯度爆炸與之相反)總體來說就是梯度相當(dāng)不穩(wěn)定。
2.控制過擬合可以減少或不用dropout
3.降低網(wǎng)絡(luò)對初始化權(quán)重不敏感
4.允許使用較大的學(xué)習(xí)率
所以使用BN可以使得模型訓(xùn)練更加容易和穩(wěn)定。BN從字面意思來說就是每一批數(shù)據(jù)進行歸一化,這里分批在前面的數(shù)據(jù)準備里已經(jīng)進行了分批處理。BN可以在網(wǎng)絡(luò)中任意一層進行歸一化處理,V3-inception使用到的優(yōu)化器是SGD。
沒有使用BN的時候每層的值迅速全部變?yōu)榱?,也就是說所有的神經(jīng)元都已經(jīng)死了,而有BN,relu過后,每層的值都能有一個比較好的分布效果。


QQ截圖20190604122213.png

數(shù)據(jù)如果在梯度很小的區(qū)域,那么學(xué)習(xí)率就會很慢甚至長時間停滯,但是減均值除方差后,數(shù)據(jù)就被移到中心區(qū)域,如右圖所示,對于大多數(shù)激活函數(shù)來說,這個區(qū)域的梯度都是很大的。這個用來解決梯度消失。但是如果每一層都是這樣做的話,數(shù)據(jù)的分布總是隨著變化敏感的區(qū)域,相當(dāng)于不用考慮數(shù)據(jù)分布變化了這樣訓(xùn)練起來更有效率。但是減均值除方差得到的分布是正態(tài)分布,但是并不是正態(tài)分布就是最好或者最能體現(xiàn)我們訓(xùn)練樣本的特征分布。因為數(shù)據(jù)本身很多情況下是不對稱的,或者激活函數(shù)未必是對方差為1的數(shù)據(jù)最好的效果,就比如sigmoid激活函數(shù),在-1到1之間的梯度變化不大。這樣的話對于非線性變化的作用就不能很好的提現(xiàn),換言之就是,均方誤差操作后可能會削弱網(wǎng)絡(luò)的性能,所以再加一步利用優(yōu)化變一下方差大小和均值位置,使得新的分布更切合數(shù)據(jù)的真實分布,保證模型的非線性表達能力。

卷積層

作用:通過在原始圖像上平移來提取特征

tf.nn.conv2(input,fitter,strides,padding)

input:是傳入四個維度的圖片或者上一層卷積得到的tensor
fitter:卷積核相當(dāng)于權(quán)重有初始值有形狀,
strides:步長大小,決定卷積核每次移動的步長,決定了卷積后的圖片大小。
padding:可設(shè)置為‘’SAME“,"VALID"當(dāng)padding=SAME時下一層的圖片長寬計算new_widh=w/s(向上取整)。padding=VALID時new_width=(w-f+1)/s。w為圖片的長寬,f是卷積核大小,s是步長

激活函數(shù)

作用:增加非線性分割能力,對輸入的數(shù)據(jù)原始空間進行扭曲。

  • relu
    1,有效的解決了梯度小時問題
    2,計算速比較快
    SGD:(批梯度下降)的求解速度遠快于sigmoid和tanh
    sigmoid:采用sigmoid缺點:計算量相對大,而采用relu激活函數(shù),整個過程的計算量節(jié)省很多,在深層神經(jīng)網(wǎng)絡(luò)中,sigmoid函數(shù)反向傳播時很容易出現(xiàn)梯度消失的情況

池化層

作用:減小學(xué)習(xí)參數(shù),降低網(wǎng)絡(luò)的復(fù)雜度
池化層分為最大池化和平均池化,一般最常用最大池化,最大池化是在卷積核大小的feature_map上取最大值,因為這個最大值可以反映了這個feature周圍的特征。
內(nèi)部的池化窗口和卷積核類似,以及步長,padding

Incpetion V3中將5×5的卷積替換成了兩個3×3的卷積
而且在這個module中還是用了卷積的分解,將一個7×7的卷積拆分成了一個1×7的卷積和一個7×1的卷積,不僅能夠大大節(jié)省參數(shù)降低模型的過擬合,還能比一個7×7的卷積多一個非線性的變換。另外inceptionv3將卷積網(wǎng)絡(luò)進行了拆分,其結(jié)果比對稱的拆分為幾個相同的小卷積核效果更明顯,可以處理更多,更豐富的空間特征,增加特征多樣性。

  • LSTM

對于LSTM神經(jīng)網(wǎng)絡(luò)無論是從什么角度描述,中間做的一堆事情,還是找什么樣的特征是最適合做這樣的一個分類任務(wù),最終連接softmax是用于分類。時序t就是每個單詞輸入的先后順序,它結(jié)合上一時刻的輸出同時乘以權(quán)重當(dāng)做這一時刻的輸入
20181205233257613.png

定義RNN的基本單元

lstm_cell=tf.contrib.rnn.BasicLSTMCell(num_units=512,state_is_tuple=True)

為了防止過擬合,在LSTM中也添加了dropout層,分別使input,和output的值控制在0.7

lstm_cell=tf.contrib.rnn.DropoutWrapper(lstm_cell,input_keep_prob=0.7,
output_keep_prob=0.7)

定義圖中的隱狀態(tài):hi,可以把隱狀態(tài)視作記憶體,它捕捉了之前時間點上的信息。記憶體在RNN迭代的過程也在不斷地更新內(nèi)部的記憶,就像人的大腦一樣,不斷地記住新的東西,又在忘記舊的

獲得lstm全零狀態(tài)
zero_state=lstm_cell.zero_state(batch_size=batch_size,dtype=tf.float32)
更新lstm狀態(tài),這里將經(jīng)過CNN后提取得到的特征向量輸入到lstm_cell
_,initial_state=lstm_cell(self.image_embeddings,zero_state)

定義RNN循環(huán),在這里將句子的特征向量self.seq_embeddings輸入到RNN中.sequence_length:圖片對應(yīng)的caption的句子長度。
initial_state:更新后的initial_state。

lstm_outputs, _ = tf.nn.dynamic_rnn(cell=lstm_cell, inputs=self.seq_embeddings,
sequence_length=sequence_length,
initial_state=initial_state,
dtype=tf.float32,
scope=lstm_scope)

在lstm最后添加一個全連接層作為最終的輸出
num_outputs:定義輸出的維度
weights_initializer:設(shè)置權(quán)重參數(shù),
該函數(shù)默認使用relu的激活函數(shù)

logits = tf.contrib.layers.fully_connected(
inputs=lstm_outputs,
num_outputs=10000,
activation_fn=None,
weights_initializer=self.initializer,
scope=logits_scope)

2.原理

  • 構(gòu)造損失函數(shù)

損失函數(shù)使用softmax的交叉熵損失函數(shù),target是logits經(jīng)過向右移動一后得到的caption的id,target經(jīng)過tf.cast(tf.reshape(self.seq_target,[-1]),dtype=tf.float32)后才能傳到交叉熵中計算logits對于target的偏離程度

方法1
losses=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=targets)

weights:是一個數(shù)值全為1的shape=[batch_size*word_size]的一維數(shù)組
因為每個批次的數(shù)據(jù)都會產(chǎn)生不同的loss值,將每個批次得到的損失值除以批次大小,得到每個批次的平均損失

batch_loss=tf.div(tf.reduce_sum(tf.multiply(losses,weights)),tf.reduce_sum(weights),name="batch_loss")
tf.losses.add_loss(batch_loss)
total_loss=tf.losses.get_total_loss()

方法2


正確的答案,這里將[batch_size,num_steps]二維數(shù)組轉(zhuǎn)換為一維數(shù)組損失的權(quán)重。在這里所有的權(quán)重都為1,也就是說不同batch和不同時刻的重要程度是一樣的。
 loss=tf.contrib.legacy_seq2seq.sequence_loss_by_example(
 [logits],[tf.reshape(self.targets,[-1][tf.ones([batch_size*num_steps],dtype=tf.float32)] )
  計算得到每個batch的平均損失
  total_cost=tf.reduce_sum(loss)/batch_size

3.實驗

  • 訓(xùn)練

    • 超參數(shù)

      1.learning_rate

      指數(shù)衰減法:

      如果staircase=True,代表每decay_step步更新一次learning_rate,如果staircase=False,那就每次迭代都會更新學(xué)習(xí)率。學(xué)習(xí)率計算方法
      image

最初設(shè)置learning_rate=2.0
tf.train.exponential_decay(learning_rate,global_step,decay_steps=decay_step,decay_rate=0.5 , staircase=True)
1,global_step:用于衰減計算的全局步數(shù)。喂入一次batch_size 計為一次global_step
2,decay_step:衰減速度(num_examples_per_epoch/batch_size)*num_epochs_per_decay
num_example_per_epoch:所有的image_caption的數(shù)量
batch_size:batch_size一般設(shè)置為2的n次冪,這里設(shè)置為32
num_epochs_per_decay設(shè)置的是8
3,decay_rate:衰減系數(shù)

多項式學(xué)習(xí)率衰減

polynomial_decay(learning_rate, global_step, decay_steps,end_learning_rate=0.0001, power=1.0,cycle=False, name=None):

在對抗神經(jīng)網(wǎng)絡(luò)中使用的一種學(xué)習(xí)率衰減方法,特點是確定結(jié)束的學(xué)習(xí)率,學(xué)習(xí)率更新公式是:

decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) + end_learning_rate

對于神經(jīng)網(wǎng)絡(luò)中三個參數(shù)的概念:

epoch: 訓(xùn)練時,所有訓(xùn)練數(shù)據(jù)都訓(xùn)練一次,即所有數(shù)據(jù)的個數(shù)
batch:使用訓(xùn)練集中的一小部分樣本對模型進行一次反向傳播的參數(shù)更新,這一小部分樣本稱為“一批數(shù)據(jù)”。
batch_size: 在訓(xùn)練集中選擇一組樣本用來更新權(quán)值。一個batch_size包含的樣本數(shù)目,通常設(shè)為2的n次冪,常用的包括32,64,128,256,網(wǎng)絡(luò)較小的時候使用256,較大時使用32,或者16.

實例:

數(shù)據(jù)集中有50000張訓(xùn)練的圖片數(shù)量,現(xiàn)在選擇batch_size=256對模型進行訓(xùn)練。

  • 每個epoch要訓(xùn)練的圖片數(shù)量:50000

  • 訓(xùn)練集具有的batch數(shù)50000/256=196(向上取整)

  • 每個epoch需要完成的batch數(shù)196

  • 每個epoch中發(fā)生的模型權(quán)重更新次數(shù):196

  • 不同次的epoch訓(xùn)練雖然用的都是訓(xùn)練集的五萬張圖片,但是對模型的權(quán)重跟新值卻是不同的,因為不同次的模型處于的loss在空間上的不同位置,模型的訓(xùn)練次數(shù)越靠后,越接近谷底,loss也就越小。

優(yōu)化函數(shù)

優(yōu)化函數(shù)使用的是隨機梯度下降SGD:SGD是每一次迭代計算mini-batch的梯度,然后對參數(shù)進行更新,計算梯度的方法是求偏導(dǎo),對于訓(xùn)練數(shù)據(jù)集,我們首先將其分成n個batch,每個batch包含m個樣本。我們每次更新都利用一個batch的數(shù)據(jù),而非整個訓(xùn)練集、
優(yōu)點:
當(dāng)訓(xùn)練數(shù)據(jù)太多時,將訓(xùn)練集分成一個一個批次,可以減少機器的壓力,并且可以更快地收斂

  • 測試

  • 運行結(jié)果

p是概率,因為生成的圖片描述不是只有三句,所以三句話的概率和不為零,只是挑選了三句概率最大的打印出來。

QQ瀏覽器截圖20190526085307.png
  • 結(jié)果分析
效果由于在訓(xùn)練時loss值沒有下降到最小,所以效果不是太好,圖中是兩個長頸鹿站在草地上,但是在后面兩句將長頸鹿預(yù)測成大象。

參考鏈接:

1.在構(gòu)建讀取隊列時可以開啟多線程:https://zhuanlan.zhihu.com/p/47760620https://zhuanlan.zhihu.com/p/40588218
2.在lstm的構(gòu)建和理解:https://www.cnblogs.com/hypnus-ly/p/8407905.html
3.caption的詞向量方面:https://www.bilibili.com/video/av35575799/?p=7
4.cnn模型https://blog.csdn.net/loveliuzz/article/details/79135583

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容