1. 程式人生 > 程式設計 >TensorFlow keras卷積神經網路 新增L2正則化方式

TensorFlow keras卷積神經網路 新增L2正則化方式

我就廢話不多說了,大家還是直接看程式碼吧!

model = keras.models.Sequential([
 #卷積層1
 keras.layers.Conv2D(32,kernel_size=5,strides=1,padding="same",data_format="channels_last",activation=tf.nn.relu,kernel_regularizer=keras.regularizers.l2(0.01)),#池化層1
 keras.layers.MaxPool2D(pool_size=2,strides=2,padding="same"),#卷積層2
 keras.layers.Conv2D(64,activation=tf.nn.relu),#池化層2
 keras.layers.MaxPool2D(pool_size=2,#資料整理
 keras.layers.Flatten(),#1024個,全連線層
 keras.layers.Dense(1024,#100個,全連線層
 keras.layers.Dense(100,activation=tf.nn.softmax)
 ])
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
 
from tensorflow.python.keras.datasets import cifar100
from tensorflow.python import keras
import tensorflow as tf
 
class CNNMnist(object):
 
 model = keras.models.Sequential([
 #卷積層1
 keras.layers.Conv2D(32,activation=tf.nn.softmax)
 ])
 
 def __init__(self):
 (self.x_train,self.y_train),(self.x_test,self.y_test) = cifar100.load_data()
 
 self.x_train = self.x_train/255.0
 self.x_test = self.x_test/255.0
 
 
 def compile(self):
 CNNMnist.model.compile(optimizer=keras.optimizers.Adam(),loss=keras.losses.sparse_categorical_crossentropy,metrics=["accuracy"])
 
 def fit(self):
 CNNMnist.model.fit(self.x_train,self.y_train,epochs=1,batch_size=32)
 
 def evaluate(self):
 test_loss,test_acc = CNNMnist.model.evaluate(self.x_test,self.y_test)
 print(test_loss,test_acc)
 
if __name__ == '__main__':
 cnn = CNNMnist()
 print(CNNMnist.model.summary())
 cnn.compile()
 cnn.fit()

補充知識:初步瞭解TensorFlow如何實現正則化

為了避免過擬合問題,一個非常常用的方法是正則化(regularization),正則化的思想就是在損失函式中加入刻畫模型複雜程度的指標。

假設用於刻畫模型在訓練資料上表現的損失函式為J(θ),那麼在優化時不是直接優化J(θ),而是優化J(θ) + λR(w),其中R(w)刻畫的是模型的複雜程度,而λ表示模型複雜損失在總損失中的比例,需要注意的是,這裡的θ表示的是一個神經網路中所有的引數,它包括邊上的權重w和偏置項b,但一般來說模型複雜度只由權重w決定。

常用的刻畫模型複雜度的函式R(w)有兩種,一種是L1正則化,計算公式是:

TensorFlow keras卷積神經網路 新增L2正則化方式

另一種是L2正則化,計算公式是:

TensorFlow keras卷積神經網路 新增L2正則化方式

TensorFlow可以優化任意形式的損失函式,所以TensorFlow自然也可以優化帶正則化的損失函式。

L1正則化和L2正則化,在TensorFlow中分別以不同的函式實現它們,以下列程式碼為示例:

#含有L1正則化的損失函式:
loss = tf.reduce_mean(tf.square(y_ - y)) + tf.contrib.layers.l1_regularizer(λ)(w)

#含有L2正則化的損失函式:
loss = tf.reduce_mean(tf.square(y_ - y)) + tf.contrib.layers.l2_regularizer(λ)(w)

loss為定義的損失函式,它由兩個部分組成,第一個部分是均方誤差損失函式,它刻畫了模型在訓練資料上的表現,第二個部分就是正則化,它防止模型過度模擬訓練資料中的隨機噪音;

λ表示了正則化項的權重,w為需要計算正則化損失的引數。

TensorFlow提供了tf.contrib.layers.l1_regularizer函式和tf.contrib.layers.l2_regularizer函式用來計算L1正則化和L2正則化,通過以下程式碼給出使用兩個函式的樣例:

import tensorflow as tf
weights = tf.constant([[1.0,-2.0],[-3.0,4.0]])
with tf.Session() as sess:
 #計算結果為5.0
 print(sess.run(tf.contrib.layers.l1_regularizer(0.5)(weights)))
 #計算結果為15 * 1/2 = 7.5,L2正則化乘以1/2可以方便求導
 print(sess.run(tf.contrib.layers.l2_regularizer(0.5)(weights)))

在簡單的神經網路中,這樣的方式就可以很好地計算帶正則化的損失函數了,但當神經網路的引數增多之後,這樣的方式首先可能導致損失函式loss的定義很長,可讀性差且容易出錯,更主要的是,當網路結構複雜之後定義網路結構的部分和計算損失函式的部分可能不在同一個函式中,這樣通過變數這種方式計算損失函式就不方便了。

為了解決這個問題,可以使用TensorFlow中提供的集合(collection)來維護需要計算的正則化損失,以下列程式碼為示例給出通過集合計算一個5層神經網路帶L2正則化的損失函式的計算方法:

import tensorflow as tf

#獲取一層神經網路邊上的權重,並將這個權重的L2正則化損失加入名稱為losses的集合中
def get_weight(shape,r):
 #生成一個變數
 var = tf.Variable(tf.random_normal(shape,stddev=1,seed=1),dtype=tf.float32)
 '''add_to_collection函式將這個新生成變數的L2正則化損失項加入集合
 這個函式的第一個引數losses是集合的名字,第二個引數是要加入這個集合的內容'''
 tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(r)(var))
 return var

x = tf.placeholder(tf.float32,shape=(None,2))
y_ = tf.placeholder(tf.float32,1))

#定義了每一層網路中節點的個數
layer_dimension = [2,10,1]
#神經網路的層數
n_layers = len(layer_dimension)

#這個變數維護前向傳播時最深層的節點,開始的時候就是輸入層
cur_layer = x
#in_dimension為當前層的節點個數
in_dimension = layer_dimension[0]

#通過一個迴圈來生成5層全連線的神經網路結構
for i in range(1,n_layers):
 #out_dimension為下一層的節點個數
 out_dimension = layer_dimension[i]
 #生成當前層中權重的變數,並將這個變數的L2正則化損失加入losses集合
 weight = get_weight([in_dimension,out_dimension],0.001)
 bias = tf.Variable(tf.fill([1,0.1))
 #使用ReLU啟用函式
 cur_layer = tf.nn.relu(tf.matmul(cur_layer,weight) + bias)
 #進入下一層之前將下一層的節點個數更新為當前層節點個數
 in_dimension = out_dimension

'''在定義神經網路前向傳播的同時已經將所有的L2正則化損失加入了losses集合
這裡只需要計算刻畫模型在訓練資料上表現的損矣函式。'''
mse_loss = tf.reduce_mean(tf.square(y_ - cur_layer))

#將均方誤差損失函式加入損失集合
tf.add_to_collection('losses',mse_loss)

'''get_collection返回一個列表,這個列表包含所有這個集合中的元素
在這個樣例中這些元素就是損失函式的不同部分,將它們加起來就可以得到最終的損失函式。'''
loss = tf.add_n(tf.get_collection('losses'))

以上這篇TensorFlow keras卷積神經網路 新增L2正則化方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。