keras實現EDSR中遇到的坑

最近需要實現超分辨率問題,但EDSR模型不適合自己的數據集,故重新用keras寫了一遍,以下是遇到的坑:

1、批量讀取圖片

        因爲內存不夠的問題,嘗試了h5py,train_on_batch,以及fit_generator三種不同的加載大數據集的方式,最後感覺還是fit_generator好用,生成器代碼如下(訓練和標籤均爲圖片):

def generator(index_list,path,batch_size):
    list_x=[]
    list_y=[] 
    count=0
    i = 0
    while 1:
        f = index_list[i%len(index_list)]
        img_path1 = path + 'low/' + f
        img_path2 = path + 'high/' + f
        img_data = image.load_img(img_path1)
        img_label = image.load_img(img_path2)
        img_array = image.img_to_array(img_data)
        img_array2 = image.img_to_array(img_label)
        list_x.append(img_array)
        list_y.append(img_array2)
        count+=1
        i = i+1
        if count>=batch_size: #數據記錄達到batch_size才返回
            yield (np.array(list_x), np.array(list_y))
            count=0
            list_x=[];list_y=[]

2、殘差縮放問題

        在原論文中,爲了防止訓練一段時間梯度消失或爆炸的問題(自己訓練時20個epoch就會爆炸),引入了縮放因子,即將層中所有數都乘以一個數(此處爲0.1),在tensorflow代碼中,只需要直接乘以0.1即可,但keras並不支持此操作,因此在此處引入了lambda函數,lambda函數用以對上一層的輸出施以任何Theano/TensorFlow表達式,但只接收一個變量,即上一層的輸出。

#殘差塊
def scale(output_layer):
        return output_layer * 0.1
def Resblock(x,channels=64,kernel_size=(3,3)):
    tmp = Conv2D(channels, kernel_size, strides=1, padding='same', activation='relu')(x)
    tmp = Conv2D(channels, kernel_size, strides=1, padding='same')(tmp)
    tmp = Lambda(scale)(tmp)
    z = add([x, tmp])
    return z

3、定義本論文的殘差網絡,只需要將殘差塊寫好,然後使用一個for循環即可堆疊,十分簡便

4、訓練好模型後再保存,會報錯,此時需要加入custom_objects,即model = load_model('model3.h5',custom_objects={'PSNR_':PSNR_,'scale':scale}),並將自定義的函數重新載入。

但還有一個問題是,會報一些其他錯誤,錯誤原因是將在gpu訓練好的模型放在cpu模型下導入,則會產生錯誤。訓練和加載的環境需要一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章