dnn神经网络_机器学习-浅谈神经网络和Keras的应用
神經(jīng)網(wǎng)絡(luò)是深度學(xué)習(xí)的基礎(chǔ),它在人工智能中有著非常廣泛的應(yīng)用,它既可以應(yīng)用于咱們前面的章節(jié)所說的Linear Regression, classification等問題,它還廣泛的應(yīng)用于image recognition,NLP 等等應(yīng)用中,當(dāng)然啦,這一節(jié)咱們主要講述神經(jīng)網(wǎng)絡(luò)的最基礎(chǔ)的結(jié)構(gòu)以及應(yīng)用,在后面我會逐漸的講解基于咱們的這個最簡單的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的一些其他方面的優(yōu)化和提升,例如有RNN,CNN等等。這一節(jié)主要講解一下咱們的神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu),以及如何用TensorFlow和Keras構(gòu)建一個神經(jīng)網(wǎng)絡(luò),以及常用的一些存儲,加載網(wǎng)絡(luò)模型的一些方式。
- 神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)咱們已經(jīng)聽過很多次了,可是它具體長什么樣,它的結(jié)構(gòu)是什么樣子呢?只要大家看懂了下面的圖,大家就能理解最基本的神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)了,我會結(jié)合著下面的圖來解釋DNN的一些基本概念
上面的DNN的圖片是我自己畫的,它是一個最基本的DNN的結(jié)構(gòu);一個神經(jīng)網(wǎng)絡(luò)其實主要包括三個部分,分別是Input layer, hidden layers 和 output layer。input layer就是相當(dāng)于咱們的數(shù)據(jù)輸入,input layer中每一個node都是一個feature,如果咱們的dataset有5個feature,那么咱們的input layer就有5個node;最后一個output layer相當(dāng)于咱們的target,output layer的node也有可能是多個的不一定只有一個node哦,例如如果咱們的target是class, 假設(shè)一共有10中classes的可能,那么這里的target就是一個one-hot encoding的數(shù)據(jù),每一個target都有10個元素,那么這時候咱們output layer的node就是10個了。Hidden layers則是咱們用戶定義的layer了,要根據(jù)具體的問題具體的分析,如果咱們的問題很復(fù)雜,則hidden layer就越多,咱們運算的速度也就越慢,反之亦然;如果細心的朋友肯定會注意到咱的DNN圖片還有另外一種紅色的layer,那就是activation layer,這是什么呢??這是因為在咱們的DNN如果沒有activation layer,那么咱們可以想象的出,咱們的模型無論是多么的復(fù)雜,咱最終的模型都是線性的,這時候咱們的模型只適合于linear regression的情況;對于想classification的問題,咱們必須要加一些非線性的函數(shù)來讓咱們的DNN模型最終能夠用于non-linear的情況,activation layer就是這些非線性的函數(shù),這里主要用到的有sigmoid, softmax和relu。所以在linear的情況時候,咱們是不需要activation layer的,在non-linear的問題中,咱們則必須要要用activation layer。另外,DNN圖片中中的weight咱們都是用箭頭表示的,咱們在訓(xùn)練一個DNN的時候,其實也就是的不多的訓(xùn)練這些weight,通過gradient descent的方式最終找出最合理的weights,這些weights的初始值有很多種方式來設(shè)定,既可以都設(shè)置成零,也可以按照一定的規(guī)則設(shè)置成隨機數(shù),在tf.keras中有很多種方式來設(shè)置初始值的。上面就是一個最簡單的DNN的結(jié)構(gòu),以及這個結(jié)構(gòu)的一些基本的概念,至于咱們是如何來訓(xùn)練這個模型的,通過什么方式來求這個DNN的gradient descent的,這中間其實涉及到了DNN 的back propagation的,具體細節(jié)我會在后面的章節(jié)細講的。這里大家主要理解一個forward propagation的DNN的結(jié)構(gòu)和過程,以及他的應(yīng)用就行了。下面我就講述一下如何用TensorFlow和Keras來應(yīng)用實現(xiàn)上面的DNN。
- TensorFlow應(yīng)用之實現(xiàn)DNN
這里咱們講述一下如何用TensorFlow來定義咱們的DNN,并且訓(xùn)練DNN模型。其實在TensorFlow中,訓(xùn)練DNN的過程跟我前面隨筆中寫的linear regression的流程是一模一樣的,從數(shù)據(jù)準(zhǔn)備一種的最后的模型的evaluation都是一樣的,只是在模型的定義中有一點點細微的區(qū)別,我在這里把整個流程的代碼都貼出來,然后分析一下他跟其他模型訓(xùn)練的一些不同點
import pandas as pdimport numpy as npimport tensorflow as tffrom sklearn import metricsimport math"Step1: Data preparation"#data loadingcali_housing_price_origin = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv")generator = np.random.Generator(np.random.PCG64())cali_housing_price_permutation = cali_housing_price_origin.reindex(generator.permutation(cali_housing_price_origin.index))#preprocess featuresdef preprocess_data(data_frame): feature_names = ["longitude", "housing_median_age", "total_rooms", "total_bedrooms", "population", "households", "median_income"] data_frame=data_frame.copy() features = data_frame[feature_names] features["rooms_per_person"]=features["total_rooms"]/features["population"] return features#preprocess targetsdef preprocess_targets(data_frame): target = pd.DataFrame() target["median_house_value"] = data_frame["median_house_value"]/1000.0 return targetfeatures = preprocess_data(cali_housing_price_permutation)target = preprocess_targets(cali_housing_price_permutation)#trainningfeatures_trainning = features.head(12000)target_trainning = target.head(12000)#validationfeatures_validation = features.tail(5000)target_validation = target.tail(5000)"Step2: Building a neuro network"#construct feature columnsdef construct_feature_columns(features): return [tf.feature_column.numeric_column(my_feature) for my_feature in features]#construct input functiondef input_func(features,target,shuffle,epoches,batch_size): features = {key:np.array([value]).T for key,value in dict(features).items()} ds = tf.data.Dataset.from_tensor_slices((features,target)) ds = ds.batch(batch_size).repeat(epoches) if shuffle: ds = ds.shuffle(10000) feature,lable = tf.compat.v1.data.make_one_shot_iterator(ds).get_next() return feature,lable#model define and trainning process definitiondef train_DNN_model(feature_trainning,target_trainning,feature_validation,target_validation, steps): my_optimizer = tf.optimizers.SGD(learning_rate = 0.001, clipnorm = 5) DNN_regressor = tf.estimator.DNNRegressor(feature_columns = construct_feature_columns(feature_trainning), optimizer = my_optimizer, hidden_units = [10,10]) input_func_trainning = lambda: input_func(feature_trainning, target_trainning, shuffle=True, epoches=None, batch_size=100) DNN_regressor.train(input_fn = input_func_trainning, steps = steps) return DNN_regressor"Step 3: making predictions"DNN_regressor = train_DNN_model(features_trainning, target_trainning, features_validation, target_validation, 2000)#datasource for predictions#predicting trainning datasetinput_fn_trainning = lambda: input_func(features = features_trainning, target=target_trainning, shuffle=False, epoches=1, batch_size=1)predictions_trainning = DNN_regressor.predict(input_fn = input_fn_trainning)#extract and format the datasetpredictions_trainning = np.array([item["predictions"][0] for item in predictions_trainning])#MSEmse = metrics.mean_squared_error(target_trainning, predictions_trainning)咱們可以看出來,它的整個流程還是一樣,只在一個地方后其他的模型訓(xùn)練過程不一樣,那就是選擇TensorFlow的estimator中的模型不一樣而已,例如上面的是一個線性的DNN,咱們選擇的就是下面的DNNRegression
DNN_regressor = tf.estimator.DNNRegressor(feature_columns = construct_feature_columns(feature_trainning), optimizer = my_optimizer, hidden_units = [10,10])注意上面定義模型的參數(shù),它多了一個hidden_units參數(shù),這就是用戶自定義的hidden layers的部分,如果咱們的結(jié)果不理想,咱們可以適當(dāng)?shù)脑黾觝idden_units的數(shù)量。上面的是一個線性的DNN的模型定義,那么如果咱們的是non-linear的模型,例如classification,咱們?nèi)绾味x呢?請看下面的代碼
DNN_classifier = tf.estimator.DNNClassifier(hidden_units = [100,100], feature_columns = configure_column_features(), optimizer = my_optimizer, n_classes = 10, activation_fn=tf.nn.relu)如果咱們的模型是non-linear的classification problem,那么咱們就選擇estimator中的DNNClassifier模型,這里咱們可以看出它也增加了很多參數(shù),n_classes是說明咱們的數(shù)據(jù)一共有多少個classes,默認(rèn)值是2;activation_fn是選擇的relu; 這些值都是用戶根據(jù)實際情況自定義的,我這里的只是一個最簡單的演示。其實他還有很多很多參數(shù)可以定義,大家自己去看文檔根據(jù)實際的情況來定義。
- 神經(jīng)網(wǎng)絡(luò)之Keras應(yīng)用
上面咱們介紹了用TensorFlow的estimator來定義和訓(xùn)練神經(jīng)網(wǎng)絡(luò),但是在實際中有一個更加強大的框架來專門處理深度學(xué)習(xí)的問題,那就是無敵的Keras。Keras自己是一個獨立的框架,專門用來處理深度學(xué)習(xí)的相關(guān)問題,咱們可以直接下載并且導(dǎo)入它的組件進行應(yīng)用;但是呢,無敵的TensorFlow早就為了方便大家而提前將Keras導(dǎo)入到了TensorFlow的tf.keras這個模塊中了,所以大家也不需要單獨的來導(dǎo)入了,直接就用TensorFlow中的tf.keras模塊就能實現(xiàn)幾乎所有的Keras的功能。首先,咱們也是來看一下用Keras最簡單的方式搭建一個DNN并且訓(xùn)練這個神經(jīng)網(wǎng)絡(luò)。
第一步:網(wǎng)絡(luò)結(jié)構(gòu)搭建
#import kerasimport tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layersimport numpy as np##1.build a sequential networkmodel = keras.Sequential()#add a full-connected and dense layermodel.add(layers.Dense(64,activation ='relu',input_shape=(32,)))#add an another layer with l2 regularizermodel.add(layers.Dense(50, activation = 'sigmoid', kernel_regularizer = keras.regularizers.l2(0.01), bias_regularizer = keras.regularizers.l2(0.02), bias_initializer = keras.initializers.Ones(), kernel_initializer = 'glorot_uniform' ) )#add another layer with l2 and l1 regularizermodel.add(layers.Dense(40, activation = 'relu', kernel_regularizer = keras.regularizers.l2(0.01), bias_regularizer = keras.regularizers.l1(0.01)))#add another layer with l1,l2 regularizer and bias/kernel initializermodel.add(layers.Dense(10,activation = 'softmax'))"""首先咱們初始化咱們神經(jīng)網(wǎng)絡(luò)的layers, 咱們的網(wǎng)絡(luò)有多少的layers,咱們就初始化多少個Dense layer實例。然后將這些layers按照順序的一次加入到咱們的model對象中。這里每一個Dense layer咱們都可以用戶自定義很多的參數(shù),我在上面的例子中也展示了很多種例子,例如有:activation, regularizer, initializer等等很多,如果大家去看他的文檔,大家會看到更多的參數(shù),但是在實際中,咱們主要就是設(shè)置上面的例子中展示的一些參數(shù)。但是這里有一個小細節(jié)大家一定要注意,否很容易出現(xiàn)runtime error,而且非常難找到原因,那就是bias_initializer和kernel_initializer的選擇,這里并不是隨便選擇一個initializer就行的,首先kernel_initializer是一個matrix,所以它所選擇的initializer必須得是返回matrix的,例如上面例子中的glorot_uniform等等,而bias_initializer則是一個一維的vector!!!記住bias是vector而不是matrix,所以它所選擇的initializer則必須得是返回一維的vector的的initializer,而不能是glorot_uniform, othogonal等initializer。這里的細節(jié)很容易讓人忽略,而一旦出錯卻很難找到原因的。另外一點,input layer是不需要定義的,Keras是自動的會把咱們的input layer加進去的,但是output layer是需要咱們手動定義并且加上去的。所以上面的模型結(jié)構(gòu)是一個input layer, 三個hidden layers和一個output layer。咱們也可以通過model.summary()的方法來檢查咱們的模型結(jié)構(gòu),如下所示
上面就是model.summary()返回的結(jié)果,它默認(rèn)也沒有顯示input layer。
第二步:配置上面定義的模型結(jié)構(gòu)
model.compile( optimizer = keras.optimizers.Adam(0.01), loss = 'mse', metrics = ['mae'])這一步主要是給上面定義的網(wǎng)絡(luò)模型配置一些基本的信息,例如optimizer, loss function和metrics這些模型必要的一些信息。這里跟咱們之前講的其他的一些基本模型都是一樣的,這里就不在贅述了,如果不知道就看我前面的博客。
第三部: 數(shù)據(jù)準(zhǔn)備
這部分內(nèi)容呢既可以放在咱們的第一步,也可以放在咱們的網(wǎng)絡(luò)模型都定義好了之后,這里我就隨機產(chǎn)生幾個數(shù)據(jù)當(dāng)做咱們的數(shù)據(jù)模型,方便咱們后面內(nèi)容的演示
data = np.random.random((1000,32))labels = np.random.random((1000,10))val_data = np.random.random((100,32))val_labels = np.random.random((100,10))dataset = tf.data.Dataset.from_tensor_slices((data,labels))dataset = dataset.batch(32)val_dataset = tf.data.Dataset.from_tensor_slices((val_data,val_labels))val_dataset = val_dataset.batch(32)第四步:模型訓(xùn)練
#trainning a model from datasetmodel.fit(dataset,epochs = 10, validation_data=val_dataset)這里訓(xùn)練數(shù)據(jù)的時候,咱們的數(shù)據(jù)既可以是numpy array也可以是dataset,因為我個人習(xí)慣的問題,我傾向于是有dataset的數(shù)據(jù)來訓(xùn)練,所以我上面的例子也是用的dataset。上面epochs的參數(shù)是說明咱們的模型訓(xùn)練的時候,咱們一共重復(fù)咱們的數(shù)據(jù)集多少次。
第五步:predict 和 evaluation
#predictionmodel.predict(data)#evaluationmodel.evaluate(dataset)- Keras Functional APIs (save & load model)
上面只是展示了如何用Keras搭建并且訓(xùn)練一個最簡單的神經(jīng)網(wǎng)絡(luò),那么實際中咱們遇到的會遇到一些其他的需求,例如當(dāng)咱們的模型訓(xùn)練后,咱們?nèi)绾伪4孢@個模型呢?如何保存咱們訓(xùn)練得來的weights呢?如何加載咱們存儲在本地的模型呢?如何加載咱們的weights呢?這些都是咱們肯定會遇到的問題。那么這些功能性的API都是如何應(yīng)用呢?咱們這里就一個個的給大家介紹一下。
第一:存儲/加載 整個模型
#save a entire modelmodel.save("C:/Users/tangx/OneDrive/Desktop/path_to_my_model.h5")#load a entire modelmodel = keras.models.load_model("C:/Users/tangx/OneDrive/Desktop/path_to_my_model.h5")上面第一步就是將咱們訓(xùn)練的模型(包括模型的結(jié)構(gòu)和weights, bias等所有的信息)都存儲在本地的指定的位置。第二句代碼就是加載整個咱們的本地的模型,當(dāng)然了,這個加載后的模型也是包括了所有的信息,包括了模型結(jié)構(gòu),weights和bias所有的信息。
第二:存儲/加載 咱們的weights和bias
在有些情況下,咱們只想加載咱們訓(xùn)練出來的weights(包括了bias啊),那么這種情況下,咱們?nèi)绾未鎯δ?#xff1f;看下面的代碼
#only save weightsmodel.save_weights("C:/Users/tangx/OneDrive/Desktop/model_wights")上面是Keras提供的將咱們model的weights(包括bias)存儲在本地的方式,注意哦, 這里只是存儲了weights哦,并沒有這個model的結(jié)構(gòu)哦,那么咱們?nèi)绾瓮暾募虞d這個模型呢?光有weights而沒有網(wǎng)絡(luò)結(jié)構(gòu)的話可是沒有用的哦。那么接下來看一下如何通過加載weights來加載整個模型信息呢,首先咱們得知道這個weights所對應(yīng)的網(wǎng)絡(luò)結(jié)構(gòu),然后重新定義并且初始化一個相對應(yīng)的神經(jīng)網(wǎng)絡(luò),相當(dāng)于獲取的一個“空模型“, 然后用下面的代碼將weights填充到這個“空模型”中
#restore the model's state, which requires a model with same architecturemodel.load_weights("C:/Users/tangx/OneDrive/Desktop/model_wights")這之后,相當(dāng)于給咱們的model填充了模型內(nèi)容,從而咱們的model就可以進行正常的操作了,例如predict,evaluate等等。
第三: 存儲/加載 網(wǎng)絡(luò)結(jié)構(gòu)和配置(serialize a model)
從上面的內(nèi)容咱們可以知道,如果咱們只存儲了weights的話,咱們在下次加載整個模型的時候,咱們還得自己重新定義并且實例化一個網(wǎng)絡(luò)結(jié)構(gòu)和配置,然后咱們才能加載咱們的weights,從而讓這個模型可用。可以實際中咱們也可以單獨的只存儲/加載這個模型的結(jié)構(gòu)和配置。那么咱們?nèi)绾巫瞿?#xff1f;看下面代碼演示
#save and recreate a model's configuration without any weights(serilizes a model to json format)json_string = model.to_json()#recreate a model archetechture and configuration from json string without any weightsfresh_model = keras.models.model_from_json(json_string)上面第一句代碼呢就是將咱們的模型架構(gòu)和配置信息轉(zhuǎn)成json的數(shù)據(jù)結(jié)構(gòu)存儲起來,記住啊,這里只存儲了網(wǎng)絡(luò)架構(gòu)和配置信息,并不包括訓(xùn)練得來的weights,這里的過程也稱作model serialization。第二句代碼就是從咱們序列化json數(shù)據(jù)格式中,加載咱們的網(wǎng)絡(luò)結(jié)構(gòu)和網(wǎng)絡(luò)配置信息。從而咱們也可以直接將這個fresh_model用來load_weights, 從而成為一個完成的模型。
總結(jié)
以上是生活随笔為你收集整理的dnn神经网络_机器学习-浅谈神经网络和Keras的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang string 加号连接性能
- 下一篇: 谷歌:不守规矩的“顽童”