日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

keras concatenate_Keras结合Keras后端搭建个性化神经网络模型

發布時間:2024/10/14 编程问答 138 豆豆
生活随笔 收集整理的這篇文章主要介紹了 keras concatenate_Keras结合Keras后端搭建个性化神经网络模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Keras是基于Tensorflow等底層張量處理庫的高級API庫。它幫我們實現了一系列經典的神經網絡層(全連接層、卷積層、循環層等),以及簡潔的迭代模型的接口,讓我們能在模型層面寫代碼,從而不用仔細考慮模型各層張量之間的數據流動。

  但是,當我們有了全新的想法,想要個性化模型層的實現,Keras的高級API是不能滿足這一要求的,而換成Tensorflow又要重新寫很多輪子,這時,Keras的后端就派上用場了。Keras將底層張量庫的函數功能統一封裝在“backend”中,用戶可以用統一的函數接口調用不同的后端實現的相同功能。所以,如果不追求速度的話,可以僅使用Keras實現你的任何獨特想法,從而避免使用原生Tensorflow寫重復的輪子。

  我們定義并訓練一個神經網絡模型需要考慮的要素有三個:層、損失函數、優化器。而我們創新主要在于前兩個,因此下面介紹如何結合Keras高級API與后端,自定義特殊神經網絡層以及損失函數。

1 自定義網絡層

  自定義層可以通過兩種方式實現:使用Lambda層和繼承Layer類。

1.1 lambda層

  Lambda層僅能對輸入做固定的變換,并不能定義可以通過反向傳播訓練的參數(通過Keras的fit訓練),因此能實現的東西較少。以下代碼實現了Dropout的功能:

from keras import backend as Kfrom keras import layersdef my_layer(x): mask = K.random_binomial(K.shape(x),0.5) return x*mask*2x = layers.Lambda(my_layer)(x)

  其中my_layer函數是自定義層要實現的操作,傳遞參數只能是Lambda層的輸入。定義好函數后,直接在layers.Lambda中傳入函數對象即可。實際上,這些變換不整合在lambda層中而直接寫在外面也是可以的:

from keras import backend as Kfrom keras import layersx = layers.Dense(500,activation='relu')(x) mask = K.random_binomial(K.shape(x),0.5)x = x*mask*2

  數據先經過一個全連接層,然后再被0.5概率Dropout。以上實現Dropout只是作舉例,你可以以同樣的方式實現其它的功能。

1.2 繼承layer類

  如果你想自定義可以訓練參數的層,就需要繼承實現Keras的抽象類Layer。主要實現以下三個方法:

  1、__init__(self, *args, **kwargs):構造函數,在實例化層時調用。此時還沒有添加輸入,也就是說此時輸入規模未知,但可以定義輸出規模等與輸入無關的變量。類比于Dense層里的units、activations參數。

  2、build(self, input_shape):在添加輸入時調用(__init__之后),且參數只能傳入輸入規模input_shape。此時輸入規模與輸出規模都已知,可以定義訓練參數,比如全連接層的權重w和偏執b。

  3、call(self, *args, **kwargs):編寫層的功能邏輯。

1.2.1 單一輸入

  當輸入張量只有一個時,下面是實現全連接層的例子:

import numpy as npfrom keras import layers,Model,Input,utilsfrom keras import backend as Kimport tensorflow as tfclass MyDense(layers.Layer): def __init__(self, units=32): #初始化 super(MyDense, self).__init__()#初始化父類 self.units = units #定義輸出規模 def build(self, input_shape): #定義訓練參數 self.w = K.variable(K.random_normal(shape=[input_shape[-1],self.units])) #訓練參數 self.b = tf.Variable(K.random_normal(shape=[self.units]),trainable=True) #訓練參數 self.a = tf.Variable(K.random_normal(shape=[self.units]),trainable=False) #非訓練參數 def call(self, inputs): #功能實現 return K.dot(inputs, self.w) + self.b #定義模型input_feature = Input([None,28,28]) x = layers.Reshape(target_shape=[28*28])(input_feature)x = layers.Dense(500,activation='relu')(x) x = MyDense(100)(x)x = layers.Dense(10,activation='softmax')(x) model = Model(input_feature,x) model.summary() utils.plot_model(model)

  模型結構如下:

  在build()中,訓練參數可以用K.variable或tf.Variable定義。并且,只要是用這兩個函數定義并存入self中,就會被keras認定為訓練參數,不管是在build還是__init__或是其它函數中定義。但是K.variable沒有trainable參數,不能設置為Non-trainable params,所以還是用tf.Variable更好更靈活些。

1.2.2 多源輸入

  如果輸入包括多個張量,需要傳入張量列表。實現代碼如下:

import numpy as npfrom keras import layers,Model,Input,utilsfrom keras import backend as Kimport tensorflow as tfclass MyLayer(layers.Layer): def __init__(self, output_dims): super(MyLayer, self).__init__() self.output_dims = output_dims def build(self, input_shape): [dim1,dim2] = self.output_dims self.w1 = tf.Variable(K.random_uniform(shape=[input_shape[0][-1],dim1])) self.b1 = tf.Variable(K.random_uniform(shape=[dim1])) self.w2 = tf.Variable(K.random_uniform(shape=[input_shape[1][-1],dim2])) self.b2 = tf.Variable(K.random_uniform(shape=[dim2])) def call(self, x): [x1, x2] = x y1 = K.dot(x1, self.w1)+self.b1 y2 = K.dot(x2, self.w2)+self.b2 return K.concatenate([y1,y2],axis = -1) #定義模型input_feature = Input([None,28,28])#輸入x = layers.Reshape(target_shape=[28*28])(input_feature) x1 = layers.Dense(500,activation='relu')(x) x2 = layers.Dense(500,activation='relu')(x) x = MyLayer([100,80])([x1,x2]) x = layers.Dense(10,activation='softmax')(x) model = Model(input_feature,x) model.summary() utils.plot_model(model,show_layer_names=False,show_shapes=True)

  模型結構如下:

  總之,傳入張量列表,build傳入的input_shape就是各個張量形狀的列表。其它都與單一輸入類似。

2 自定義損失函數

  根據Keras能添加自定義損失的特性,這里將添加損失的方法分為兩類:

  1、損失需要根據模型輸出與真實標簽來計算,也就是只有模型的輸出與外部真實標簽作為計算損失的參數。

  2、損失無需使用外部真實標簽,也就是只用模型內部各層的輸出作為計算損失的參數。

  這兩類損失添加的方式并不一樣,希望以后Keras能把API再改善一下,這種冗余有時讓人摸不著頭腦。

2.1 第一類損失

  這類損失可以通過自定義函數的形式來實現。函數的參數必須是兩個:真實標簽與模型輸出,不能多也不能少,并且順序不能變。然后你可以在這個函數中定義你想要的關于輸出與真實標簽之間的損失。然后在model.compile()中將這個函數對象傳給loss參數。代碼示例如下(參考鏈接):

def customed_loss(true_label,predict_label): loss = keras.losses.categorical_crossentropy(true_label,predict_label) loss += K.max(predict_label) return lossmodel.compile(optimizer='rmsprop', loss=customed_loss)

  如果硬是想用這種方法把模型隱層的輸出拿來算損失的話,也不是不可以。只要把相應隱層的輸出添加到模型的輸出列表中,自定義損失函數就可以從模型輸出列表中取出隱層輸出來用了。即:

model = Model(input,[model_output, hidden_layer_output])

  當然,這樣就把模型結構改了,如果不想改模型的結構而添加“正則化”損失,可以使用下面的方法。

2.2 第二類損失

  這類損失可以用Model.add_loss(loss)方法實現,loss可以使用Keras后端定義計算圖來實現。但是顯然,計算圖并不能把未來訓練用的真實標簽傳入,所以,add_loss方法只能計算模型內部的“正則化”損失。

  add_loss方法可以使用多次,損失就是多次添加的loss之和。使用了add_loss方法后,compile中就可以不用給loss賦值,不給loss賦值的話使用fit()時就不能傳入數據的標簽,也就是y_train。如果給compile的loss賦值,最終的目標損失就是多次add_loss添加的loss和compile中loss之和。另外,如果要給各項損失加權重的話,直接在定義loss的時候加上即可。代碼示例如下:

loss = 100000*K.mean(K.square(somelayer_output))#somelayer_output是定義model時獲得的某層輸出model.add_loss(loss)model.compile(optimizer='rmsprop')

  以上講的都是關于層輸出的損失,層權重的正則化損失并不這樣添加,自定義正則項可以看下面。

  keras中添加正則化_Bebr的博客-CSDN博客_keras 正則化

  里面介紹了已實現層的自定義正則化,但沒有介紹自定義層的自定義正則化,這里先挖個坑,以后要用再研究。

總結

以上是生活随笔為你收集整理的keras concatenate_Keras结合Keras后端搭建个性化神经网络模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。