圖像識(shí)別往往包含數(shù)以百萬(wàn)計(jì)的參數(shù),從頭訓(xùn)練需要大量打好標(biāo)簽的圖片,還需要大量的計(jì)算力(往往數(shù)百小時(shí)的GPU時(shí)間)。對(duì)此,遷移學(xué)習(xí)是一個(gè)捷徑,他可以在已經(jīng)訓(xùn)練好的相似工作模型基礎(chǔ)上,繼續(xù)訓(xùn)練新的模型。
這里我們將基于ImageNet訓(xùn)練好的模型,對(duì)適當(dāng)數(shù)量(數(shù)千張)圖像進(jìn)行訓(xùn)練,這個(gè)訓(xùn)練可能需要30分鐘左右。

準(zhǔn)備工作
安裝tensorflow-hub,這是一個(gè)類(lèi)似于tensorflow模型市場(chǎng)集散地的應(yīng)用,這個(gè)練習(xí)將使用它的一個(gè)模型作為基礎(chǔ)模型。
安裝命令:
pip3 install --upgrade tensorflow-hub
從百度網(wǎng)盤(pán)下載再訓(xùn)練需要使用的花圖片集(密碼:lzjg)
下載后解壓,得到幾個(gè)文件夾,分別包含了菊花daisy、蒲公英dandelion、玫瑰rose、向日葵sunflow和郁金香tulips各種花的圖片,總計(jì)有幾千張。
讀取圖片列表create_image_lists
將菊花、蒲公英等各種文件夾下的圖片路徑都讀取出來(lái),再把每個(gè)分類(lèi)的圖片按照訓(xùn)練70%、測(cè)試20%、驗(yàn)證10%的比例拆分,組合成字典格式:
{
dir: name,
trainging: [imgage_paths],
testing: [imgage_paths],
validation: [imgage_paths]
}
為了將圖片按照70%20%10%進(jìn)行分類(lèi),這里使用的方法是哈?;募?/p>
- 將文件名轉(zhuǎn)為hash值(40個(gè)數(shù)字字母組合)
- 再把hash值轉(zhuǎn)為整數(shù)(非常大的數(shù)字)
- 利用取余數(shù)運(yùn)算%MAX把大整數(shù)放縮到0~MAX之間
- 0-MAX再除以MAX得到0-1隨機(jī)小數(shù),再乘以100得到百分?jǐn)?shù)
- 判斷這個(gè)百分?jǐn)?shù)屬于哪一段,就把文件名歸到哪一段
以下是代碼及注解,很長(zhǎng),耐心看:
import argparse
import collections
from datetime import datetime
import hashlib
import random
import re
import sys
import os
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub
dir_path = os.path.dirname(os.path.realpath(__file__))
image_dir=os.path.join(dir_path,'flower_photos')
MAX_IPC = 2 ** 27 - 1 #每分類(lèi)最大圖片數(shù)max-image-per-class
#要使用的hub模型,就是module_name
HUB_MODULE='https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/1'
#hub模型中要使用的量化操作節(jié)點(diǎn)名
FAKE_QUANT_OPS = ('FakeQuantWithMinMaxVars',
'FakeQuantWithMinMaxVarsPerChannel')
def create_image_lists():
result = collections.OrderedDict() #有序字典,匹配順序到labels
sub_dirs = sorted(x[0] for x in tf.gfile.Walk(image_dir)) #獲得花類(lèi)型文件夾列表,第一個(gè)是根目錄
is_root_dir = True
for sub_dir in sub_dirs:
if is_root_dir: #跳過(guò)根目錄
is_root_dir = False
continue
extensions = ['jpg', 'jpeg', 'JPG', 'JPEG']
file_list = []
dir_name = os.path.basename(sub_dir) #得到花分類(lèi)的名字daisy,rose...
if dir_name == image_dir:
continue
for extension in extensions:
file_glob = os.path.join(image_dir, dir_name, '*.' + extension) #獲取所有圖片路徑
file_list.extend(tf.gfile.Glob(file_glob)) #將所有圖片路徑加入到file_list
label_name = re.sub(r'[^a-z0-9]+', ' ', dir_name.lower()) #清理花分類(lèi)名稱(chēng)字符,這里沒(méi)意義
training_images = [] #用于訓(xùn)練的圖片路徑
testing_images = [] #用于測(cè)試的圖片路徑
validation_images = [] #用于驗(yàn)證的圖片路徑
for file_name in file_list:
base_name = os.path.basename(file_name) #得到文件名7166550328_de0d73cfa9.jpg...
hash_name = re.sub(r'_nohash_.*$', '', file_name) #得到圖片全路徑
hash_name_hashed = hashlib.sha1(tf.compat.as_bytes(hash_name)).hexdigest() #轉(zhuǎn)40位hash
hash_int=int(hash_name_hashed, 16) #轉(zhuǎn)超長(zhǎng)的整數(shù)
hash_per=hash_int%(MAX_IPC + 1)*(100.0 / MAX_IPC) #放縮到0~100
if hash_per < 10: #驗(yàn)證集10%
validation_images.append(base_name)
elif hash_per < 30: #測(cè)試集20%
testing_images.append(base_name)
else: #訓(xùn)練集70%
training_images.append(base_name)
result[label_name] = {
'dir': dir_name,
'training': training_images,
'testing': testing_images,
'validation': validation_images,
}
return result
#入口函數(shù)
def main(_):
create_image_lists();
#模塊或應(yīng)用
if __name__ == '__main__':
tf.app.run()
最終輸出的result格式:
([
('daisy', {
'dir': 'daisy',
'training': ['14167534527_781ceb1b7a_n.jpg',...],
'testing': ['20773528301_008fcbc5a1_n.jpg',...],
'validation': ['721595842_bacd80a6ac.jpg',...]
}),
('dandelion', {
'dir': 'dandelion',
'training': ['14167534527_781ceb1b7a_n.jpg',...],
'testing': ['20773528301_008fcbc5a1_n.jpg',...],
'validation': ['721595842_bacd80a6ac.jpg',...]
}),
...
])
獲取圖片全路徑的函數(shù)get_image_path
首先利用上面的create_image_lists方法生成圖片列表,然后可以在下面函數(shù)中直接使用它。
get_image_path函數(shù)主要是從image_lists中恢復(fù)出某個(gè)圖片路徑。
增加和修改的代碼
#所有圖片列表對(duì)象
image_lists=create_image_lists()
#獲取一個(gè)圖片路徑,label_name花類(lèi)名同dir_name,category是training/testingvalidation,index是圖片索引,set_dir可替換flower_photos文件夾名
def get_image_path(label_name,category,index,set_dir=image_dir):
label_lists = image_lists[dir_name]
category_list = label_lists[category]
mod_index = index % len(category_list) #避免超出長(zhǎng)度范圍
base_name = category_list[mod_index]
sub_dir = label_lists['dir']
full_path = os.path.join(image_dir, sub_dir, base_name)
return full_path
#入口函數(shù)
def main(_):
get_image_path('daisy','training',66)
如果把上面返回的full_path打印出來(lái),大概是
/Users/zhyuzh/desktop/.../flower_photos/daisy/267148092_4bb874af58.jpg
生成瓶頸文件路徑的函數(shù)get_bottleneck_path
Bottleneck瓶頸文件是對(duì)原始眾多圖片數(shù)據(jù)進(jìn)行整理后的數(shù)據(jù)文件,能夠更加方便的被tensorflow調(diào)用來(lái)訓(xùn)練、檢驗(yàn)或預(yù)測(cè)使用。具體創(chuàng)建方法在下面會(huì)詳解,這里只是先生成一個(gè)存放瓶頸文件的目錄。
以下是修改和增加的代碼
bottleneck_dir=os.path.join(dir_path,'bottlenecks')
#獲取一個(gè)瓶頸文件路徑的函數(shù)
def get_bottleneck_path(label_name, category,index):
module_name = (HUB_MODULE.replace('://', '~') # URL scheme.
.replace('/', '~') # URL and Unix paths.
.replace(':', '~').replace('\\', '~')) # Windows paths.
return get_image_path(label_name, category,index,bottleneck_dir) + '_' + 'module_name' + '.txt' #為了簡(jiǎn)化路徑,我們臨時(shí)使用字符串module_name而不是變量
#入口函數(shù)
def main(_):
bnpath=get_bottleneck_path('daisy','training',66)
print(bnpath)
從hub.ModuleSpec生成圖和模型的函數(shù)create_module_graph
因?yàn)槲覀儾⒉皇峭耆珡念^開(kāi)始訓(xùn)練模型,而是在hub的某個(gè)模型的基礎(chǔ)上進(jìn)行再訓(xùn)練,所以首先我們要從hub上拉取模型信息,并從中恢復(fù)出原計(jì)算圖graph的一些張量參數(shù)以便于使用。
#要使用的hub模型
HUB_MODULE='https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/1'
#hub模型中要使用的量化操作節(jié)點(diǎn)名
FAKE_QUANT_OPS = ('FakeQuantWithMinMaxVars',
'FakeQuantWithMinMaxVarsPerChannel')
#創(chuàng)建從一個(gè)hub.ModuleSpec生成計(jì)算圖并從Hub載入模型的函數(shù)
#module_spec需要使用的hub.ModuleSpec,bottleneck_tensor模型輸出的額bottleneck_tensor值
#resized_input_tensor模型期望的輸入的圖像數(shù)據(jù)的尺寸,wants_quantization是否要量化
def create_module_graph(module_spec):
height, width = hub.get_expected_image_size(module_spec)
with tf.Graph().as_default() as graph:
resized_input_tensor = tf.placeholder(tf.float32, [None, height, width, 3])
m = hub.Module(module_spec)
bottleneck_tensor = m(resized_input_tensor)
wants_quantization = any(node.op in FAKE_QUANT_OPS
for node in graph.as_graph_def().node) #any任何一個(gè)為真即為真
return graph, bottleneck_tensor, resized_input_tensor, wants_quantization
#入口函數(shù)
def main(_):
module_spec = hub.load_module_spec(HUB_MODULE)
result=create_module_graph(module_spec)
print(result)
輸出結(jié)果如下,包含了graph, bottleneck_tensor, resized_input_tensor, wants_quantization四個(gè)字段:
(
<tensorflow.python.framework.ops.Graph object at 0x11b3da668>,
<tf.Tensor 'module_apply_default/hub_output/feature_vector/SpatialSqueeze:0' shape=(?, 1280) dtype=float32>,
<tf.Tensor 'Placeholder:0' shape=(?, 224, 224, 3) dtype=float32>,
False
)
提取圖片瓶頸值的函數(shù)run_bottleneck_on_image
上面的代碼我們從hub獲得了模型,并提取到了graph計(jì)算圖,這個(gè)函數(shù)將使用計(jì)算圖中的兩個(gè)張量進(jìn)行運(yùn)算,先對(duì)圖片進(jìn)行調(diào)整尺寸轉(zhuǎn)為張量,然后提取它的瓶頸張量值。
以下是增加的代碼,暫時(shí)不運(yùn)行它,稍后和下面的函數(shù)一起測(cè)試:
#對(duì)一張圖片執(zhí)行推斷,提取瓶頸總結(jié)層summary layer
#sess當(dāng)前session,image_data字符串格式j(luò)peg數(shù)據(jù),image_data_tensor圖的輸入數(shù)據(jù)層
#decoded_image_tensor圖像改變尺寸和處理后的輸出,resized_input_tensor識(shí)別圖的輸入節(jié)點(diǎn)
#bottleneck_tesnor最終softmax之前的層
#返回瓶頸值數(shù)組numpy array
def run_bottleneck_on_image(sess, image_data, image_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor):
resized_input_values = sess.run(decoded_image_tensor, #解碼JPEG,調(diào)整大小,放縮像素值
{image_data_tensor: image_data}) #feed_dict
bottleneck_values = sess.run(bottleneck_tensor, #使用識(shí)別網(wǎng)絡(luò)運(yùn)行它
{resized_input_tensor: resized_input_values}) #feed_dict
bottleneck_values = np.squeeze(bottleneck_values) #去掉冗余的數(shù)組嵌套,簡(jiǎn)化形狀
return bottleneck_values
創(chuàng)建瓶頸文件的函數(shù)create_bottleneck_file
首先我們創(chuàng)建ensure_dir_exists函數(shù),確保文件夾存在,不存在的話(huà)就創(chuàng)建它。
然后在create_bottleneck_file函數(shù)中我們先用上面創(chuàng)建的get_bottleneck_path方法獲取存儲(chǔ)文件路徑bottleneck_path,同樣獲取圖片路徑image_path并讀取圖片數(shù)據(jù)image_data,使用上面創(chuàng)建的run_bottleneck_on_image函數(shù)把圖片數(shù)據(jù)利用session和graph內(nèi)的張量,轉(zhuǎn)為瓶頸值并保存到文件中。
以下是新增代碼,仍然不能運(yùn)行,因?yàn)閰?shù)jpeg_data_tensor, decoded_image_tensor還無(wú)法獲得,稍后我們會(huì)一起測(cè)試:
#確保目錄路徑存在,不存在就創(chuàng)建
def ensure_dir_exists(dir_name):
if not os.path.exists(dir_name):
os.makedirs(dir_name)
#創(chuàng)建一個(gè)瓶頸文件
def create_bottleneck_file(sess,label_name,category, index, jpeg_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor):
sub_dir=os.path.join(dir_path,'bottlenecks/'+label_name)
ensure_dir_exists(sub_dir) #創(chuàng)建文件夾
bottleneck_path=get_bottleneck_path(label_name, category,index) #存儲(chǔ)瓶頸文件的路徑
tf.logging.info('正在創(chuàng)建bottleneck文件:' + bottleneck_path)
image_path = get_image_path(label_name,category,index) #獲取圖片文件全路徑
image_data = tf.gfile.FastGFile(image_path, 'rb').read() #獲取文件原數(shù)據(jù)
try:
bottleneck_values = run_bottleneck_on_image( #從圖片生成瓶頸值
sess,image_data, jpeg_data_tensor, decoded_image_tensor,
resized_input_tensor, bottleneck_tensor)
except Exception as e:
raise RuntimeError('處理文件出錯(cuò) %s (%s)' % (image_path,str(e)))
bottleneck_string = ','.join(str(x) for x in bottleneck_values)
with open(bottleneck_path, 'w') as bottleneck_file:
bottleneck_file.write(bottleneck_string) #將獲得的bottleneck值用逗號(hào)連接成字符串寫(xiě)入文件
向計(jì)算圖添加圖片解碼操作的函數(shù)add_jpeg_decoding
jpg_data_tensor是一個(gè)placeholder,decoded_image_tensor是調(diào)整過(guò)大小的圖像數(shù)據(jù)張量格式。
下面是新增和修改的代碼,可以結(jié)合上面兩個(gè)函數(shù)一起測(cè)試運(yùn)行:
#添加操作,執(zhí)行jpeg解碼和調(diào)整大小 ,返回兩個(gè)張量jpeg_data_tensor,decoded_image_tensor
def add_jpeg_decoding(module_spec):
input_height, input_width = hub.get_expected_image_size(module_spec)
input_depth = hub.get_num_image_channels(module_spec)
jpeg_data = tf.placeholder(tf.string, name='DecodeJPGInput')
decoded_image = tf.image.decode_jpeg(jpeg_data, channels=input_depth)
#將全范圍的unit8轉(zhuǎn)為0~1范圍的float32
decoded_image_as_float = tf.image.convert_image_dtype(decoded_image,tf.float32)
decoded_image_4d = tf.expand_dims(decoded_image_as_float, 0) #擴(kuò)充形狀的維度
resize_shape = tf.stack([input_height, input_width]) #通過(guò)合并提升維度
resize_shape_as_int = tf.cast(resize_shape, dtype=tf.int32)
resized_image = tf.image.resize_bilinear(decoded_image_4d,
resize_shape_as_int) #放縮圖像尺寸
return jpeg_data, resized_image
#入口函數(shù)
def main(_):
module_spec = hub.load_module_spec(HUB_MODULE)
graph, bottleneck_tensor, resized_input_tensor, wants_quantization = (
create_module_graph(module_spec))
with tf.Session(graph=graph) as sess:
init = tf.global_variables_initializer()
sess.run(init)
jpeg_data_tensor, decoded_image_tensor = add_jpeg_decoding(module_spec)
create_bottleneck_file(sess,'daisy','training', 65, jpeg_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor)
在main函數(shù)里面我們先是利用hub.load_module_spec載入了模型,然后使用create_module_graph創(chuàng)建了圖,已經(jīng)從圖中提取的bottleneck_tensor和resized_inpt_tensor。
然后我們利用graph創(chuàng)建了session,初始化了變量,又使用add_jpeg_decoding方法創(chuàng)建了兩個(gè)張量jpeg_data_tensor和decoded_image_tensor。
最后我們使用create_bottleneck_file方法,在/bottlenecks/daisy/目錄下創(chuàng)建了一個(gè)文件,并把我們得到的圖片bottleneck數(shù)據(jù)寫(xiě)入其中。
這個(gè)文件的都是很多的浮點(diǎn)小數(shù),這些數(shù)字在另外的角度上反映了像素之間的關(guān)系,而tensorflow能夠從中更加容易的找到規(guī)律:
1.1014792,1.7321489,0.284751,0.7904396,0.0,0.11441692,0.0,0.30288044,0.07657591,0.353643,0.0,1.2191151,0.3042915,1.0002377,0.18627474,0.4791365,0.0,0.058162533,1.0755428,0.047679365,0.0,1.5222605,0.51027495,0.109168105,0.3694405,0.014923426,0.0032605443,2.3457944,0.5158326...
階段小結(jié)
這階段我們主要編寫(xiě)了幾個(gè)函數(shù),實(shí)現(xiàn)了圖像文件的列表生成、bottleneck文件的創(chuàng)建的內(nèi)容:
- 讀取圖片列表create_image_lists
- 獲取圖片全路徑的函數(shù)get_image_path
- 生成瓶頸文件路徑的函數(shù)get_bottleneck_path
- 從hub.ModuleSpec生成圖和模型的函數(shù)create_module_graph
- 提取圖片瓶頸值的函數(shù)run_bottleneck_on_image
- 確保路徑文件夾存在的函數(shù)ensure_dir_exists
- 創(chuàng)建瓶頸文件的函數(shù)create_bottleneck_file
- 向計(jì)算圖添加圖片解碼操作的函數(shù)add_jpeg_decoding
以下是此階段的全部代碼:
import argparse
import collections
from datetime import datetime
import hashlib
import random
import re
import sys
import os
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub
dir_path = os.path.dirname(os.path.realpath(__file__))
image_dir=os.path.join(dir_path,'flower_photos')
bottleneck_dir=os.path.join(dir_path,'bottlenecks')
MAX_IPC = 2 ** 27 - 1 #每分類(lèi)最大圖片數(shù)max-image-per-class
#要使用的hub模型,就是module_name
HUB_MODULE='https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/1'
#hub模型中要使用的量化操作節(jié)點(diǎn)名
FAKE_QUANT_OPS = ('FakeQuantWithMinMaxVars',
'FakeQuantWithMinMaxVarsPerChannel')
#獲取全部文件列表
def create_image_lists():
result = collections.OrderedDict() #有序字典,匹配順序到labels
sub_dirs = sorted(x[0] for x in tf.gfile.Walk(image_dir)) #獲得花類(lèi)型文件夾列表,第一個(gè)是根目錄
is_root_dir = True
for sub_dir in sub_dirs:
if is_root_dir: #跳過(guò)根目錄
is_root_dir = False
continue
extensions = ['jpg', 'jpeg', 'JPG', 'JPEG']
file_list = []
dir_name = os.path.basename(sub_dir) #得到花分類(lèi)的名字daisy,rose...
if dir_name == image_dir:
continue
for extension in extensions:
file_glob = os.path.join(image_dir, dir_name, '*.' + extension) #獲取所有圖片路徑
file_list.extend(tf.gfile.Glob(file_glob)) #將所有圖片路徑加入到file_list
label_name = re.sub(r'[^a-z0-9]+', ' ', dir_name.lower()) #清理花分類(lèi)名稱(chēng)字符,這里沒(méi)意義
training_images = [] #用于訓(xùn)練的圖片路徑
testing_images = [] #用于測(cè)試的圖片路徑
validation_images = [] #用于驗(yàn)證的圖片路徑
for file_name in file_list:
base_name = os.path.basename(file_name) #得到文件名7166550328_de0d73cfa9.jpg...
hash_name = re.sub(r'_nohash_.*$', '', file_name) #得到圖片全路徑
hash_name_hashed = hashlib.sha1(tf.compat.as_bytes(hash_name)).hexdigest() #轉(zhuǎn)40位hash
hash_int=int(hash_name_hashed, 16) #轉(zhuǎn)超長(zhǎng)的整數(shù)
hash_per=hash_int%(MAX_IPC + 1)*(100.0 / MAX_IPC) #放縮到0~100
if hash_per < 10: #驗(yàn)證集10%
validation_images.append(base_name)
elif hash_per < 30: #測(cè)試集20%
testing_images.append(base_name)
else: #訓(xùn)練集70%
training_images.append(base_name)
result[label_name] = {
'dir': dir_name,
'training': training_images,
'testing': testing_images,
'validation': validation_images,
}
return result
#所有圖片列表對(duì)象
image_lists=create_image_lists()
#獲取一個(gè)圖片路徑,label_name花類(lèi)名同dir_name,category是training/testingvalidation,index是圖片索引,set_dir可替換flower_photos文件夾名
def get_image_path(label_name,category,index,set_dir=image_dir):
label_lists = image_lists[label_name]
category_list = label_lists[category]
mod_index = index % len(category_list) #避免超出長(zhǎng)度范圍
base_name = category_list[mod_index]
sub_dir = label_lists['dir']
full_path = os.path.join(set_dir, sub_dir, base_name)
return full_path
#獲取一個(gè)瓶頸文件路徑的函數(shù)
def get_bottleneck_path(label_name, category,index):
module_name = (HUB_MODULE.replace('://', '~') # URL scheme.
.replace('/', '~') # URL and Unix paths.
.replace(':', '~').replace('\\', '~')) # Windows paths.
return get_image_path(label_name, category,index,bottleneck_dir) + '_' + 'module_name' + '.txt'
#創(chuàng)建從一個(gè)hub.ModuleSpec生成計(jì)算圖并從Hub載入模型的函數(shù)
#module_spec需要使用的hub.ModuleSpec,bottleneck_tensor模型輸出的額bottleneck_tensor值
#resized_input_tensor模型期望的輸入的圖像數(shù)據(jù)的尺寸,wants_quantization是否要量化
def create_module_graph(module_spec):
height, width = hub.get_expected_image_size(module_spec)
with tf.Graph().as_default() as graph:
resized_input_tensor = tf.placeholder(tf.float32, [None, height, width, 3])
m = hub.Module(module_spec)
bottleneck_tensor = m(resized_input_tensor)
wants_quantization = any(node.op in FAKE_QUANT_OPS
for node in graph.as_graph_def().node) #any任何一個(gè)為真即為真
return graph, bottleneck_tensor, resized_input_tensor, wants_quantization
#對(duì)一張圖片執(zhí)行推斷,提取瓶頸總結(jié)層summary layer
#sess當(dāng)前session,image_data字符串格式j(luò)peg數(shù)據(jù),image_data_tensor圖的輸入數(shù)據(jù)層
#decoded_image_tensor圖像改變尺寸和處理后的輸出,resized_input_tensor識(shí)別圖的輸入節(jié)點(diǎn)
#bottleneck_tesnor最終softmax之前的層
#返回瓶頸值數(shù)組numpy array
def run_bottleneck_on_image(sess,image_data, image_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor):
resized_input_values = sess.run(decoded_image_tensor, #解碼JPEG,調(diào)整大小,放縮像素值
{image_data_tensor: image_data}) #feed_dict
bottleneck_values = sess.run(bottleneck_tensor, #使用識(shí)別網(wǎng)絡(luò)運(yùn)行它
{resized_input_tensor: resized_input_values}) #feed_dict
bottleneck_values = np.squeeze(bottleneck_values) #去掉冗余的數(shù)組嵌套,簡(jiǎn)化形狀
return bottleneck_values
#確保目錄路徑存在,不存在就創(chuàng)建
def ensure_dir_exists(dir_name):
if not os.path.exists(dir_name):
os.makedirs(dir_name)
#創(chuàng)建一個(gè)瓶頸文件
def create_bottleneck_file(sess,label_name,category, index, jpeg_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor):
sub_dir=os.path.join(dir_path,'bottlenecks/'+label_name)
ensure_dir_exists(sub_dir) #創(chuàng)建文件夾
bottleneck_path=get_bottleneck_path(label_name, category,index) #存儲(chǔ)瓶頸文件的路徑
tf.logging.info('正在創(chuàng)建bottleneck文件:' + bottleneck_path)
image_path = get_image_path(label_name,category,index) #獲取圖片文件全路徑
image_data = tf.gfile.FastGFile(image_path, 'rb').read() #獲取文件原數(shù)據(jù)
try:
bottleneck_values = run_bottleneck_on_image( #從圖片生成瓶頸值
sess,image_data, jpeg_data_tensor, decoded_image_tensor,
resized_input_tensor, bottleneck_tensor)
except Exception as e:
raise RuntimeError('處理文件出錯(cuò) %s (%s)' % (image_path,str(e)))
bottleneck_string = ','.join(str(x) for x in bottleneck_values)
with open(bottleneck_path, 'w') as bottleneck_file:
bottleneck_file.write(bottleneck_string) #將獲得的bottleneck值用逗號(hào)連接成字符串寫(xiě)入文件
#添加操作,執(zhí)行jpeg解碼和調(diào)整大小 ,返回兩個(gè)張量jpeg_data_tensor,decoded_image_tensor
def add_jpeg_decoding(module_spec):
input_height, input_width = hub.get_expected_image_size(module_spec)
input_depth = hub.get_num_image_channels(module_spec)
jpeg_data = tf.placeholder(tf.string, name='DecodeJPGInput')
decoded_image = tf.image.decode_jpeg(jpeg_data, channels=input_depth)
#將全范圍的unit8轉(zhuǎn)為0~1范圍的float32
decoded_image_as_float = tf.image.convert_image_dtype(decoded_image,tf.float32)
decoded_image_4d = tf.expand_dims(decoded_image_as_float, 0) #擴(kuò)充形狀的維度
resize_shape = tf.stack([input_height, input_width])
resize_shape_as_int = tf.cast(resize_shape, dtype=tf.int32)
resized_image = tf.image.resize_bilinear(decoded_image_4d,
resize_shape_as_int)
return jpeg_data, resized_image
#入口函數(shù)
def main(_):
module_spec = hub.load_module_spec(HUB_MODULE)
graph, bottleneck_tensor, resized_input_tensor, wants_quantization = (
create_module_graph(module_spec))
with tf.Session(graph=graph) as sess:
init = tf.global_variables_initializer()
sess.run(init)
jpeg_data_tensor, decoded_image_tensor = add_jpeg_decoding(module_spec)
create_bottleneck_file(sess,'daisy','training', 65, jpeg_data_tensor,
decoded_image_tensor, resized_input_tensor,
bottleneck_tensor)
#模塊或應(yīng)用
if __name__ == '__main__':
tf.app.run()
探索人工智能的新邊界
如果您發(fā)現(xiàn)文章錯(cuò)誤,請(qǐng)不吝留言指正;
如果您覺(jué)得有用,請(qǐng)點(diǎn)喜歡;
如果您覺(jué)得很有用,感謝轉(zhuǎn)發(fā)~
END