FusionGAN解读2:跑起来
運行demo之后續補充
運行CPU版,看各部分工作原理
致命錯誤:
為了使占用內存不至于過高,使用了batch_size的融合方法
這是與源代碼不同的地方
但是,這也造成了生成圖像成了小方塊
即:test的輸入只能是完整圖像
這個理解錯了,具體原因在XMind中分析
在運行…
merge函數中
img[120X5,120X7]是總畫布
img[0:120,0:120,:] 放image[120,120,1]
配置更改:
epochs=2
train_ir等的圖片設置為1張
訓練結束,想要生成圖像,要更改main函數中:is_train->False,操作如下
代碼更改:
util.py第203行添加
padding_h,padding_w = int(padding_h),int(padding_w)
test部分,代碼更改如下:
print("Testing...") if not self.load(config.checkpoint_dir): return result = np.zeros(shape=train_label_ir.shape) #用于存儲生成的圖像的白板len_data = len(train_data_ir)batch_idxs = len_data // config.batch_size for idx in range(0, batch_idxs):idx_start = idx * config.batch_sizeidx_end = min( (idx + 1) * config.batch_size, len_data )batch_images_ir = train_data_ir[idx_start:idx_end]batch_labels_ir = train_label_ir[idx_start:idx_end]batch_images_vi = train_data_vi[idx_start:idx_end]batch_labels_vi = train_label_vi[idx_start:idx_end]temp_result = self.fusion_image.eval(feed_dict={self.images_ir: batch_images_ir, self.labels_ir: batch_labels_ir,self.images_vi: batch_images_vi,self.labels_vi: batch_labels_vi})result[idx_start:idx_end,:,:,:] = temp_result# result = result * 127.5 + 127.5 result = merge(result, [nx_ir, ny_ir])原來的代碼是:
result = self.fusion_image.eval(feed_dict={self.images_ir: train_data_ir, self.labels_ir: train_label_ir,self.images_vi: train_data_vi, self.labels_vi: train_label_vi})load函數
了解:取得path最后的文件名os.path.basename()方法
加載模型使用了方法一
try:self.sess.run(tf.global_variables_initializer())self.saver.restore(self.sess, os.sep.join([checkpoint_dir,'other_model','CGAN.model-3']))print("Model restored !")return True except Exception as e:print("Restore Error :",e)return False解釋:
batchsize=32
1張輸入圖片:768X576
每個ep: 1472個圖像需要訓練,總批數:batch_idxs=46
總批數計算方法:
total_num =int((576-132)/14+1)*int((768-132)/14+1)
batch_idxs = total_num // batchsize
sample/test_image.png
checkpoint/CGAN_120/...
步驟:
input_setup存為h5數據,再由train函數讀出
取得每個批的圖片(詳細見下面)
訓練2次d,1次g
每10批輸出一次訓練情況
####解除bug的封印
-
查看python及第三方包的版本
-
缺乏tf.python.core
pip install tensorflow-estimator==1.15.0 -
內存不足問題Windows MemoryError: Unable to allocate 6.38 GiB for an array with shape (3
-pychar跑程序未使用cuda -
按固定比例分配顯存
-
修改pycharm的運行內存
-
Backend Qt5Agg is interactive backend. Turning interactive mode on.
總覽概括
捋一捋思路
main函數中,先預定義了超參數,然后建立了模型CGAN(),緊接著進行了訓練train()
build_model分為好幾步:
對Ir,Vi設立占位符,各包含image(原料)和label(對抗)
輸入之前,對Ir和Vi各自的image進行了拼接,這樣channel變成2
然后生成融合圖像fusion
d_loss部分,根據label得到pos損失,根據fusion得到neg損失
g_loss部分,分別得到g_loss_1欺騙損失和g_loss_2輻射相似性及梯度相似性
train部分需要一些處理:
- 準備數據:
將dataset(Train_ir,Train_vi)文件夾下的bmp,tif找出并排序
讀入照片,將圖像平移為0中心,并歸一化
按14步長取輸入圖像patch,image:3333,label:2121
將它們作為準備好的輸入數據
使用np.asarray() 轉換成 dtype 數據
制作h5數據,放在./checkpoint_20/Train_ir/train.h5
將dataset(Test_ir,Test_vi)文件夾下的bmp,tif找出并排序
填充測試圖像t1: 左padding,右填充直到33; 下padding,上填充直到33
將填充后的圖像劃分為若干個33*33的輸入圖像i2,并以1個圖像作為一個輸入單元shape=(33,33,1)
制作h5數據(./checkpoint_20/Test_ir/test.h5)
返回測試圖像t1的真實尺寸,后面會以此為根據復原融合的圖
-
讀出h5數據,作為輸入
-
找出變量組,包括Generator和discriminator的(由前面由
with tf.variable_scope('discriminator'): ...語句生成) -
設置優化操作,tf.train.AdamOptimizer().minimize(self.g_loss_total,var_list=self.g_vars).降低損失是將要訓練的目的
-
開始訓練:
生成器1次:每次一個batch_size喂入,計算[Generator變量組,g_loss_total,]
訓練時在路徑’CGAN_21/CGAN.model’,保存檢查點文件
- 開始測試
保存圖片
對代碼的改動和注解
廓清概念
image_size: Iir 和 Ivi 的尺寸
label_size: generator生成的尺寸
label圖像,有vi的和ir的
作用之一:在判別器中與If對抗
作用之二:計算g_loss中Lcontent一項,它包括If和Iir的相似性,以及If梯度和Ivi梯度的相似性
utils中代碼的注解:
驗證集通常是取訓練集中的一小部分數據來檢測訓練的準確率,要共享之前訓練好的相關參數的值。這種共享方式,需要在 變量命名空間 tf.variable_scope 下進行,而且采用 tf.get_variable 的共享變量定義方式,在共享之前,必須聲明以下的參數是需要共享的,否則會重新定義。
reuse的另一種用法:直接放入scope參數
with tf.variable_scope('discriminator', reuse=reuse):指定維度求和
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BGrB1hXK-1628232138446)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\tf_reduce_sum.jpg)]
L2范數:平方-求和-取開方
參考博文
范數:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zk9b3ozk-1628232138448)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\l.jpg)].
L2范數: 可以用作正則項(防止過擬合)或損失函數(最小二乘誤差least squares error, LSE)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-e7JfeFo7-1628232138449)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\l2.jpg)]
本文代碼待解讀:像是縮放(看論文)
add_to_collection(名稱,值)
將值存儲在具有給定名稱的集合中。
請注意,集合不是set(去重),因此可以多次向集合添加值。
參數:
名稱:集合的鍵。 GraphKeys 類包含許多集合的標準名稱。
value:要添加到集合中的值。
為Graph的一個方法,可以簡單地認為Graph下維護了一個字典,key為name,value為list,而add_to_collection就是把變量添加到對應key下的list中
操作的含義待解
3. lrelu:把x<0的區域抬起來一些 比如0.2時,抬起80%
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SSi9yrOI-1628232138450)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\relu.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3vDBbOg7-1628232138451)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\lrelu.png)]
若是圖片填充,參考
model模塊中的注解:
Variable是定義變量,而get_variable是獲取變量(只不過如果獲取不到就重新定義一個變量),如果按照這種邏輯,已經基本上可以理解兩者的差異了
tf.Variable 每次都會創建新的變量,在變量名重復的時候不會報錯,而是會自動創建新的變量,只是后綴加上 _1, _2 類似的用以區別。通常 lr 或 global step 之類的輔助變量會使用它來創建。tf.get_variable() 則主要用于網絡的權值設置,它可以實現權值共享,在多 GPU 的并行計算的時候使用較多,其實通過 get 的前綴就可以很好看出它們的區別,它一定是和tf.variable_scope()共同使用的,不然二者就沒有太大的區別了。
def get_variable(name,shape=None,dtype=None,initializer=None,...):常見的initializer有:常量初始化器tf.constant_initializer、正太分布初始化器tf.random_normal_initializer、截斷正態分布初始化器tf.truncated_normal_initializer、均勻分布初始化器tf.random_uniform_initializer。tf.name_scope(‘IR_input’) 給變量"包"一層名字,方便變量管理
代碼運行見test.py
tf.concat與tf.stack都是在某個維度上對矩陣(向量)進行拼接,不同點在于前者拼接后的矩陣維度不變,后者則會增加一個維度。
拼接:第二個接在第一個后面
4.Batch Normalization :為了加速訓練對數據進行預處理,最常用的是零均值和PCA(白化).隨著網絡層次加深,導致每層間以及不同迭代的相同層的輸入分布發生改變,導致網絡需要重新適應新的分布,迫使我們降低學習率降低影響。有些人首先提出在每層增加PCA(先對數據進行去相關然后再進行歸一化),但計算量大.BN是近似白化預處理。
概括:減均值->除標準差->加個性化參數γ、β
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HwLP9ydl-1628232138452)(file:///D:\PythonFiles\paper02_FusionGAN_master\Others\BN.jpg)]
還可參考
兩個參數γ、β。這樣在訓練過程中就可以學習這兩個參數,采用適合自己網絡的BN公式
tf.contrib.layers.batch_norm(inputs,decay=0.999,center=True,scale=False,epsilon=0.001,activation_fn=None,updates_collections=tf.GraphKeys.UPDATE_OPS,... )inputs: 輸入 decay :衰減系數。合適的衰減系數值接近1.0,特別是含多個9的值:0.999,0.99,0.9。如果訓練集表現很好而驗證/測試集表現得不好,選擇小的系數(推薦使用0.9)。如果想要提高穩定性,zero_debias_moving_mean設為True center:是否有偏移?如果為True,有b偏移量;如果為False,無b偏移量 scale:input是否有縮放?如果為True,則乘以gamma。如果為False,gamma則不使用。當下一層是線性的時(例如nn.relu),由于縮放可以由下一層完成,所以可以禁用該層。 epsilon:避免被零除 activation_fn:用于激活,默認為線性激活函數 updates_collections :Collections來收集計算的更新操作。updates_ops需要使用train_op來執行。如果為None,則會添加控件依賴項以確保更新已計算到位。tf.GraphKeys 包含所有graph collection中的標準集合名
graph collection 即tf.Graph,包含兩類相關信息:
圖結構 ,圖集合(tf.add_to_collection函數允許您將對象列表與一個鍵相關聯(其中tf.GraphKeys定義了部分標準鍵),tf.get_collection則允許您查詢與鍵關聯的所有對象。
TensorFlow庫的許多組成部分會使用它:例如,當您創建tf.Variable時,系統會默認將其添加到表示“全局變量(tf.global_variables)”和“可訓練變量tf.trainable_variables)”的集合中。當您后續創建tf.train.Saver或tf.train.Optimizer時,這些集合中的變量將用作默認參數。
這部分collection的名字被稱為tf.GraphKeys,可以用來獲取不同類型的op
常見的GraphKeys
input : 輸入的要做卷積的圖片,要求為一個張量,shape為 [ batch, in_height, in_width, in_channel ],其中batch為圖片的數量,in_height 為圖片高度,in_width 為圖片寬度,in_channel 為圖片的通道數,灰度圖該值為1,彩色圖為3。(也可以用其它值,但是具體含義不是很理解)
filter: 卷積核,要求也是一個張量,shape為 [ filter_height, filter_width, in_channel, out_channels ],其中 filter_height 為卷積核高度,filter_width 為卷積核寬度,in_channel 是圖像通道數 ,和 input 的 in_channel 要保持一致,out_channel 是卷積核數量。
strides: 卷積時在圖像每一維的步長,這是一個一維的向量,[ 1, strides, strides, 1],第一位和最后一位固定必須是1
padding: string類型,值為“SAME” 和 “VALID”,表示的是卷積的形式,是否考慮邊界。"SAME"是考慮邊界,不足的時候用0去填充周圍,"VALID"則不考慮
use_cudnn_on_gpu: bool類型,是否使用cudnn加速,默認為true
博文鏈接
out_size = (w - k + 2p)/s + 1
w:Width ,
k: Kernel_size,
p:Padding_len , 因為一般兩邊都填充,所以2*p
s: stride_size
tf.reducemean()
tf.reduce_mean(input_tensor, axis=None, keep_dims=False, name=None, reduction_indices=None)
根據給出的axis在input_tensor上求平均值。除非keep_dims為真,axis中的每個的張量秩會減少1。如果keep_dims為真,求平均值的維度的長度都會保持為1.如果不設置axis,所有維度上的元素都會被求平均值,并且只會返回一個只有一個元素的張量。
tf.summary.scalar()的用法:
這個方法是添加變量到直方圖中,但是不配合其他的方法,根本就顯示不出來它的意義!
基本使用步驟:
定義變量;
讓變量添加到summary.scalar;
將summary保存到磁盤以便tensorboard顯示;
把步驟都記錄下;
cmd命令,切換到相應的文件夾下,啟動tensorborder;
然后再頁面上輸入localhost:6006
使用樣例
自動管理模式merge_all()參考和手動管理模式
summary_writer = tf.summary.FileWriter('E://result/', flush_secs=60) summary_writer.add_graph(sess.graph)#添加graph圖tf.summary.scalar('loss', loss) tf.summary.scalar('accuracy', accuracy) ##生成準確率標量圖 sum_ops = tf.summary.merge_all() #自動管理metall = sess.run(sum_ops, feed_dict={X: batch_x_test, Y: batch_y_test, keep_prob: 1.})summary_writer.add_summary(metall, global_step=step) # 寫入文件tf.placeholder構筑靜態graph -> 啟動一個session ->運行模型時feed_dict={…}喂數據
這樣做的好處在于:tensorflow幫你優化整個系統的代碼
示例
import tensorflow as tf import numpy as npx = tf.placeholder(tf.float32, shape=(1024, 1024)) y = tf.matmul(x, x)with tf.Session() as sess:#print(sess.run(y)) # ERROR:此處x還沒有賦值rand_array = np.random.rand(1024, 1024)print(sess.run(y, feed_dict={x: rand_array}))Frobenius范數: 矩陣元素的平方和再開方
f范數實際上就是衡量這個矩陣和對應的零矩陣的距離
-文中用于比較真實矩陣和估計矩陣之間的相似性
max_to_keep 參數表示要保留的最近檢查點文件的最大數量
參考這里
glob模塊用來查找文件目錄和文件,返回列表,如下是用來查找e盤中所有的exe文件
os.sep: 根據所處的平臺,自動采用相應的分隔符號
data_dir = os.sep.join(['hello', 'world']) 得到linux: 'hello/world'或者win: 'hello\world'圖像插值函數原型
sub_input = cv2.resize(sub_input, (config.image_size / 4, config.image_size / 4),interpolation=cv2.INTER_CUBIC)cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)
INTER_CUBIC: 4x4像素鄰域的雙三次插值
h5數據制作與讀取
with h5py.File(savepath, 'w') as hf:hf.create_dataset(name , value) with h5py.File(savepath, 'r') as hf:hf.get(name)#示例 with h5py.File(savepath, 'w') as hf:hf.create_dataset('data', data=data)hf.create_dataset('label', data=label) with h5py.File(path, 'r') as hf:data = np.array(hf.get('data'))label = np.array(hf.get('label'))return data, labeltf.train.AdamOptimizer
self.train_fusion_op = tf.train.AdamOptimizer(config.learning_rate).minimize(self.g_loss_total,var_list=self.g_vars)函數原型為,參考
__init__(learning_rate=0.001,... ) 可調用的方法為: .minimize(loss, global_step=None,var_list=None, #會通過更新var_list添加操作以最大限度地最小化 lossgate_gradients=GATE_OP,aggregation_method=None,colocate_gradients_with_ops=False,name=None,grad_loss=None )main中的注解:
1. 在tensorflow中,tf.app.flags.FLAGS已經轉移到tf.flags.FLAGS路徑下FLAGS = tf.app.flags.FLAGS FLAGS = tf.flags.FLAGS2. tf.app.flags.FLAGS: 在用命令行執行程序時,需要傳些參數參數為key、默認值、和參數描述 # tf.app.flags.DEFINE_string("param_name", "default_val", "description") tf.flags.DEFINE_string("key1","hello","這是一個字符串") tf.flags.DEFINE_xxx()就是添加命令行的optional argument(可選參數),而tf.flags.FLAGS可以從對應的命令行參數取出參數。3. 更改縮進:停留光標在~~~上,會有選項額外補充
Tensorflow的運行機制包括: 定義計算圖和運行計算圖兩個部分,計算圖即模型的構建
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ndd861Fc-1628232138453)(file:///D:/PythonFiles/paper02_FusionGAN_master/Others/tf_def.jpg)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-L58o78gk-1628232138453)(file:///D:/PythonFiles/paper02_FusionGAN_master/Others/tf_process.jpg)]
先定義placeholder、Variable和OP等構成一張完成計算圖Graph;
接下來通過新建Session實例啟動模型運行,Session實例會分布式執行Graph;
輸入數據,根據優化算法更新Variable,然后返回執行結果即Tensor實例。\
一個使用樣例:
import tensorflow as tf # 引入tensorflow相關包 constant_a = tf.constant('Hello World!') # 定義常量 with tf.Session() as session:print(session.run(constant_a)) # 運行圖,并獲取constant_a的執行結果注入機制: 用戶通過placeholder定義占位符并構建完整Graph后,利用Session實例.run將訓練/測試數據注入到圖中,驅動任務的實際運行
import tensorflow as tf # 引入tensorflow相關包 placeholder_a = tf.placeholder(tf.float32) # 定義placeholder實例 placeholder_b = tf.placeholder(tf.float32) add_result = tf.add(placeholder_a, placeholder_b) # OP使兩值相加 multiply_result = tf.multiply(placeholder_a, placeholder_b) # OP使兩值相加 with tf.Session() as session:# 運行圖,獲取執行結果print(session.run(add_result, feed_dict = {placeholder_a: 1.0, placeholder_b: 2.0})) # 獲取單個值print(session.run([add_result, multiply_result], feed_dict = {placeholder_a: 3.0, placeholder_b: 4.0})) # 獲取多個值session的參數有:target(指定硬件設備),graph(適用于多計算圖的場景,指定運行的計算圖),config(定義session運行配置,用tf.ComfigProto配置)
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True))###首先,填的一些小坑:導入包和版本代碼修改
pip3 install tensorflow-gpu==1.15 pip install opencv-python==4.1.1.26 pip install scipy==1.2.1修改了:xrange 為 rangeFusionGAN
FusionGAN 的代碼,一種用于紅外和可見光圖像融合的 GAN 模型
請參閱我們的以下論文以了解算法詳細信息:
gpu1.15
pip install opencv-python4.1.1.26
pip install scipy==1.2.1
修改了:xrange 為 range
參考論文,以了解算法詳細信息: 馬嘉儀、魏宇、彭偉梁、常麗和江俊軍,《“FusionGAN:用于紅外和可見光圖像融合的生成對抗網絡”》,信息融合,48,第 11-26 頁,2019 年 8 月。總結
以上是生活随笔為你收集整理的FusionGAN解读2:跑起来的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论西瓜种植的重要性
- 下一篇: 计算机课数据排序与筛选ppt,《计算机表