Unet项目解析(2):./src/retinaNN_training.py
項目GitHub主頁:https://github.com/orobix/retina-unet
參考論文:Retina blood vessel segmentation with a convolution neural network (U-net)?Retina blood vessel segmentation with a convolution neural network (U-net)
1. 導入依賴的模塊 以及 依賴的腳本
1.1 導入依賴的模塊
import numpy as np import configparserfrom keras.models import Model from keras.layers import Input, concatenate, Conv2D, MaxPooling2D, UpSampling2D, Reshape, core, Dropout from keras.optimizers import Adam from keras.callbacks import ModelCheckpoint, LearningRateScheduler from keras import backend as K from keras.utils.vis_utils import plot_model as plot from keras.optimizers import SGD- keras.layers.core
core內部定義了一系列常用的網絡層,包括全連接、激活層等
- keras.callbacks.ModelCheckpoint(filepath,monitor='val_loss', verbose=0, save_best_only=False, save_weights_only = False, mode='auto', period=1)
該回調函數將在每個epoch后保存模型到filepath;
filename:字符串,保存模型的路徑
monitor:需要監視的值
verbose:信息展示模式,0或1
save_best_only:當設置為True時,將只保存在驗證集上性能最好的模型
mode:‘auto’,‘min’,‘max’之一,在save_best_only=True時決定性能最佳模型的評判準則,例如,當監測值為val_acc時,模式應為max,當檢測值為val_loss時,模式應為min。在auto模式下,評價準則由被監測值的名字自動推斷。
save_weights_only:若設置為True,則只保存模型權重,否則將保存整個模型(包括模型結構,配置信息等)
period:CheckPoint之間的間隔的epoch數
- keras.callbacks.LearningRateScheduler(schedule)
該回調函數是學習率調度器
schedule:函數,該函數以epoch號為參數(從0算起的整數),返回一個新學習率(浮點數)
# def step_decay(epoch):
# ? ? lrate = 0.01 #the initial learning rate (by default in keras)
# ? ? if epoch==100:
# ? ? ? ? return 0.005
# ? ? else:
# ? ? ? ? return lrate
#
# lrate_drop = LearningRateScheduler(step_decay)
1.2 導入依賴的腳本文件
import sys sys.path.insert(0, '/home/shenziheng/SpyderProject/Retina_NN/lib') # 加載指向腳本文件目錄 from help_functions import * # 導入help_functions腳本文件中的所有函數 from extract_patches import get_data_training # 導入extract_patches 腳本中的 get_data_training函數2.構建Unet網絡
def get_unet(n_ch,patch_height,patch_width):inputs = Input(shape=(n_ch,patch_height,patch_width))conv1 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(inputs)conv1 = Dropout(0.2)(conv1)conv1 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv1)pool1 = MaxPooling2D((2, 2))(conv1)#conv2 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(pool1)conv2 = Dropout(0.2)(conv2)conv2 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv2)pool2 = MaxPooling2D((2, 2))(conv2)#conv3 = Conv2D(128, (3, 3), activation='relu', padding='same',data_format='channels_first')(pool2)conv3 = Dropout(0.2)(conv3)conv3 = Conv2D(128, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv3)up1 = UpSampling2D(size=(2, 2))(conv3)up1 = concatenate([conv2,up1],axis=1)conv4 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(up1)conv4 = Dropout(0.2)(conv4)conv4 = Conv2D(64, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv4)#up2 = UpSampling2D(size=(2, 2))(conv4)up2 = concatenate([conv1,up2], axis=1)conv5 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(up2)conv5 = Dropout(0.2)(conv5)conv5 = Conv2D(32, (3, 3), activation='relu', padding='same',data_format='channels_first')(conv5)#conv6 = Conv2D(2, (1, 1), activation='relu',padding='same',data_format='channels_first')(conv5)conv6 = core.Reshape((2,patch_height*patch_width))(conv6)conv6 = core.Permute((2,1))(conv6)############conv7 = core.Activation('softmax')(conv6)model = Model(inputs=inputs, outputs=conv7)sgd = SGD(lr=0.01, decay=1e-6, momentum=0.3, nesterov=False)model.compile(optimizer='sgd', loss='categorical_crossentropy',metrics=['accuracy'])return model- 使用Model來初始化一個函數式模型
model = Model(inputs=[a1, a2], outputs=[b1, b3, b3])
- 模型Model的方法compile
本函數編譯模型以供訓練,參數有
optimizer:優化器,為預定義優化器名或優化器對
loss:損失函數,為預定義損失函數名或一個目標函數
metrics:列表,包含評估模型在訓練和測試時的性能的指標,典型用法是metrics=['accuracy']如果要在多輸出模型中為不同的輸出指定不同的指標,可像該參數傳遞一個字典,例如metrics={'ouput_a': 'accuracy'}
sample_weight_mode:如果需要按時間步為樣本賦權(2D權矩陣),將該值設為“temporal”。默認為“None”,代表按樣本賦權(1D權)。如果模型有多個輸出,可以向該參數傳入指定sample_weight_mode的字典或列表。在下面fit函數的解釋中有相關的參考內容。
weighted_metrics: metrics列表,在訓練和測試過程中,這些metrics將由sample_weight或clss_weight計算并賦權
target_tensors: 默認情況下,Keras將為模型的目標創建一個占位符,該占位符在訓練過程中將被目標數據代替。如果你想使用自己的目標張量(相應的,Keras將不會在訓練時期望為這些目標張量載入外部的numpy數據),你可以通過該參數手動指定。目標張量可以是一個單獨的張量(對應于單輸出模型),也可以是一個張量列表,或者一個name->tensor的張量字典。
kwargs:使用TensorFlow作為后端請忽略該參數,若使用Theano/CNTK作為后端,kwargs的值將會傳遞給 K.function。如果使用TensorFlow為后端,這里的值會被傳給tf.Session.run
在Keras中,compile主要完成損失函數和優化器的一些配置,是為訓練服務的。
- 優化器optimizers
可以在調用model.compile()之前初始化一個優化器對象,然后傳入該函數。
- 用于維度交換的permute層
Permute層將輸入的維度按照給定模式進行重排,例如,當需要將RNN和CNN網絡連接時,可能會用到該層。
dims:整數tuple,指定重排的模式,不包含樣本數的維度。重排模式的下標從1開始。例如(2,1)代表將輸入的第二個維度重拍到輸出的第一個維度,而將輸入的第一個維度重排到第二個維度。這一點和TensorFlow很不一樣。
model.add(Permute((2, 1), input_shape=(10, 64)))
# now: model.output_shape == (None, 64, 10)
# note: `None` is the batch dimension
- Conv2D / MaxPooling2D / UpSampling2D 需要指定通道的位置
data_format:字符串,“channels_first”或“channels_last”之一,代表圖像的通道維的位置。該參數是Keras 1.x中的image_dim_ordering,“channels_last”對應原本的“tf”,“channels_first”對應原本的“th”。以128x128的RGB圖像為例,“channels_first”應將數據組織為(3,128,128),而“channels_last”應將數據組織為(128,128,3)。該參數的默認值是~/.keras/keras.json中設置的值,若從未設置過,則為“channels_last”。
- 1×1的卷積的作用
大概有兩個方面的作用:1. 實現跨通道的交互和信息整合2. 進行卷積核通道數的降維和升維。
3.加載配置文件中的訓練參數和訓練數據
#========= Load settings from Config file config = configparser.RawConfigParser() config.read('configuration.txt') #patch to the datasets path_data = config.get('data paths', 'path_local') #數據文件封裝后的文件路徑 #Experiment name name_experiment = config.get('experiment name', 'name') #training settings N_epochs = int(config.get('training settings', 'N_epochs')) #迭代的次數 batch_size = int(config.get('training settings', 'batch_size')) #訓練的批量大小 patches_imgs_train, patches_masks_train = get_data_training(DRIVE_train_imgs_original = path_data + config.get('data paths', 'train_imgs_original'),DRIVE_train_groudTruth = path_data + config.get('data paths', 'train_groundTruth'), #maskspatch_height = int(config.get('data attributes', 'patch_height')),patch_width = int(config.get('data attributes', 'patch_width')),N_subimgs = int(config.get('training settings', 'N_subimgs')),inside_FOV = config.getboolean('training settings', 'inside_FOV') #select the patches only inside the FOV (default == True) )顯示示例數據:
#========= Save a sample of what you're feeding to the neural network ========== N_sample = min(patches_imgs_train.shape[0],40) visualize(group_images(patches_imgs_train[0:N_sample,:,:,:],5),'./'+name_experiment+'/'+"sample_input_imgs").show() visualize(group_images(patches_masks_train[0:N_sample,:,:,:],5),'./'+name_experiment+'/'+"sample_input_masks").show() ? ? ?? (a)輸入的原始圖像塊實例 ? ? ? ? ? ? ?(b)圖像塊對應的分割金標準4. 調用網絡 及 保存網絡模型
#=========== Construct and save the model arcitecture ===== n_ch = patches_imgs_train.shape[1] patch_height = patches_imgs_train.shape[2] patch_width = patches_imgs_train.shape[3] #U-net 網絡 [batchsize, channels, patch_heigh, patch_width] model = get_unet(n_ch, patch_height, patch_width) print ("Check: final output of the network:") print (model.output_shape) #調用pydot顯示模型 plot(model, to_file='./'+name_experiment+'/'+name_experiment + '_model.png') #保存模型 json_string = model.to_json() with open('./'+name_experiment+'/'+name_experiment +'_architecture.json', 'w') as jsonfile:jasonfile.write(json_string)5. 訓練階段
5.1 動態調整學習率并實時保存each epoch的checkpoint數據
#采用回調函數的形式保存每個epoch數據 checkpointer = ModelCheckpoint(filepath='./'+name_experiment+'/'+name_experiment +'_best_weights.h5', verbose=1, monitor='val_loss', mode='auto', save_best_only=True) #采用回調函數的形式動態設置學習率 def step_decay(epoch):lrate = 0.01 if epoch % 1 is 0:return lrate - epoch*0.001else:return lratelrate_drop = LearningRateScheduler(step_decay)- 回調函數ModelCheckpoint()
filename:字符串,保存模型的路徑
monitor:需要監視的值
verbose:信息展示模式,0或1
save_best_only:當設置為True時,將只保存在驗證集上性能最好的模型
mode:‘auto’,‘min’,‘max’之一,在save_best_only=True時決定性能最佳模型的評判準則,例如,當監測值為val_acc時,模式應為max,當檢測值為val_loss時,模式應為min。在auto模式下,評價準則由被監測值的名字自動推斷。
save_weights_only:若設置為True,則只保存模型權重,否則將保存整個模型(包括模型結構,配置信息等)
period:CheckPoint之間的間隔的epoch數
- 回調函數LearningRateScheduler()
該回調函數是學習率調度器。
schedule:自定義函數,該函數以epoch號為參數(從0算起的整數),返回一個新學習率(浮點數)
5.2 模型訓練 model.fit
#模型訓練 model.fit(patches_imgs_train, patches_masks_train, epoch=N_epochs, batch_size=batch_size, verbose=2, shuffle=True, validation_split=0.1, callbacks=[checkpointer])真正的訓練函數,調用方法如下:
fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)本函數將模型訓練nb_epoch輪,其參數有:x:輸入數據。如果模型只有一個輸入,那么x的類型是numpy array,如果模型有多個輸入,那么x的類型應當為list,list的元素是對應于各個輸入的numpy array
y:標簽,numpy array
batch_size:整數,指定進行梯度下降時每個batch包含的樣本數。
epochs:整數,訓練終止時的epoch值,訓練將在達到該epoch值時停止
verbose:日志顯示,0為不在標準輸出流輸出日志信息,1為輸出進度條記錄, 2為每個epoch輸出一行記錄
callbacks:list,其中的元素是keras.callbacks.Callback的對象,如ModelCheckpoint()、LearningRateScheduler()等。
validation_split:0~1之間的浮點數,用來指定訓練集的一定比例數據作為驗證集。 注意,validation_split的劃分在shuffle之前,因此如果你的數據本身是有序的,需要先手工打亂再指定validation_split,否則可能會出現驗證集樣本不均勻。
validation_data:形式為(X,y)的tuple,是指定的驗證集。此參數將覆蓋validation_spilt。
shuffle:布爾值或字符串,一般為布爾值, 表示是否在訓練過程中隨機打亂輸入樣本的順序。若為字符串“batch”,則是用來處理HDF5數據的特殊情況,它將在batch內部將數據打亂。
class_weight:字典,將不同的類別映射為不同的權值,該參數用來在訓練過程中調整損失函數(只能用于訓練)
sample_weight:權值的numpy array,用于在訓練時調整損失函數(僅用于訓練)。可以傳遞一個1D的與樣本等長的向量用于對樣本進行1對1的加權,或者在面對時序數據時,傳遞一個的形式為(samples,sequence_length)的矩陣來為每個時間步上的樣本賦不同的權。這種情況下請確定在編譯模型時添加了sample_weight_mode='temporal'。
initial_epoch: 從該參數指定的epoch開始訓練,在繼續之前的訓練時有用。
6.保存和測試
#========== Save and test the last model =================== model.save_weights('./'+name_experiment+'/'+name_experiment +'_last_weights.h5', overwrite=True) #test the model score = model.evaluate(patches_imgs_test, masks_Unet(patches_masks_test), verbose=0) print('Test score:', score[0]) print('Test accuracy:', score[1])Keras中模型的保存分為兩部分分別是保存架構jasonfile.write()和權重save_weights();同時模型的讀取也包括網絡架構讀取model = model_from_json(open('').read()) 和模型訓練好的權重讀取model.load_weights('')。
具體如下所示:
json_string = model.to_json() #等價于 json_string = model.get_config() open('my_model_architecture.json','w').write(json_string) model.save_weights('my_model_weights.h5') #加載模型數據和weights model = model_from_json(open('my_model_architecture.json').read()) model.load_weights('my_model_weights.h5')模型測試:
evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)本函數按batch計算在某些輸入數據上模型的誤差。x:輸入數據,是numpy array或numpy array的list
y:標簽,numpy array
batch_size:整數,含義同fit的同名參數
verbose:日志顯示,0為不在標準輸出流輸出日志信息,1為輸出進度條記錄,只能取0或1
sample_weight:numpy array,含義同fit的同名參數
本函數返回一個測試誤差的標量值(如果模型沒有其他評價指標),或一個標量的list(如果模型還有其他的評價指標)。model.metrics_names將給出list中各個值的含義。總結
以上是生活随笔為你收集整理的Unet项目解析(2):./src/retinaNN_training.py的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国人写的编译器-值得看看
- 下一篇: INI文件编程