機器學習-淺談神經網絡和Keras的應用

  • 概述

  神經網絡是深度學習的基礎,它在人工智能中有着很是普遍的應用,它既能夠應用於我們前面的章節所說的Linear Regression, classification等問題,它還普遍的應用於image recognition,NLP 等等應用中,固然啦,這一節我們主要講述神經網絡的最基礎的結構以及應用,在後面我會逐漸的講解基於我們的這個最簡單的神經網絡結構的一些其餘方面的優化和提高,例若有RNN,CNN等等。這一節主要講解一下我們的神經網絡的結構,以及如何用TensorFlow和Keras構建一個神經網絡,以及經常使用的一些存儲,加載網絡模型的一些方式。node

  • 神經網絡

  神經網絡我們已經聽過不少次了,但是它具體長什麼樣,它的結構是什麼樣子呢?只要你們看懂了下面的圖,你們就能理解最基本的神經網絡的結構了,我會結合着下面的圖來解釋DNN的一些基本概念git

上面的DNN的圖片是我本身畫的,它是一個最基本的DNN的結構;一個神經網絡其實主要包括三個部分,分別是Input layer, hidden layers 和 output layer。input layer就是至關於我們的數據輸入,input layer中每個node都是一個feature,若是我們的dataset有5個feature,那麼我們的input layer就有5個node;最後一個output layer至關於我們的target,output layer的node也有多是多個的不必定只有一個node哦,例如若是我們的target是class, 假設一共有10中classes的可能,那麼這裏的target就是一個one-hot encoding的數據,每個target都有10個元素,那麼這時候我們output layer的node就是10個了。Hidden layers則是我們用戶定義的layer了,要根據具體的問題具體的分析,若是我們的問題很複雜,則hidden layer就越多,我們運算的速度也就越慢,反之亦然;若是細心的朋友確定會注意到咱的DNN圖片還有另一種紅色的layer,那就是activation layer,這是什麼呢??這是由於在我們的DNN若是沒有activation layer,那麼我們能夠想象的出,我們的模型不管是多麼的複雜,咱最終的模型都是線性的,這時候我們的模型只適合於linear regression的狀況;對於想classification的問題,我們必需要加一些非線性的函數來讓我們的DNN模型最終可以用於non-linear的狀況,activation layer就是這些非線性的函數,這裏主要用到的有sigmoid, softmax和relu。因此在linear的狀況時候,我們是不須要activation layer的,在non-linear的問題中,我們則必需要要用activation layer。另外,DNN圖片中中的weight我們都是用箭頭表示的,我們在訓練一個DNN的時候,其實也就是的很少的訓練這些weight,經過gradient descent的方式最終找出最合理的weights,這些weights的初始值有不少種方式來設定,既能夠都設置成零,也能夠按照必定的規則設置成隨機數,在tf.keras中有不少種方式來設置初始值的。上面就是一個最簡單的DNN的結構,以及這個結構的一些基本的概念,至於我們是如何來訓練這個模型的,經過什麼方式來求這個DNN的gradient descent的,這中間其實涉及到了DNN 的back propagation的,具體細節我會在後面的章節細講的。這裏你們主要理解一個forward propagation的DNN的結構和過程,以及他的應用就好了。下面我就講述一下如何用TensorFlow和Keras來應用實現上面的DNN。json

 

  • TensorFlow應用之實現DNN

   這裏我們講述一下如何用TensorFlow來定義我們的DNN,而且訓練DNN模型。其實在TensorFlow中,訓練DNN的過程跟我前面隨筆中寫的linear regression的流程是如出一轍的,從數據準備一種的最後的模型的evaluation都是同樣的,只是在模型的定義中有一點點細微的區別,我在這裏把整個流程的代碼都貼出來,而後分析一下他跟其餘模型訓練的一些不一樣點網絡

import pandas as pd
import numpy as np import tensorflow as tf from sklearn import metrics import math "Step1: Data preparation" #data loading cali_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 features def 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 targets def preprocess_targets(data_frame): target = pd.DataFrame() target["median_house_value"] = data_frame["median_house_value"]/1000.0 return target features = preprocess_data(cali_housing_price_permutation) target = preprocess_targets(cali_housing_price_permutation) #trainning features_trainning = features.head(12000) target_trainning = target.head(12000) #validation features_validation = features.tail(5000) target_validation = target.tail(5000) "Step2: Building a neuro network" #construct feature columns def construct_feature_columns(features): return [tf.feature_column.numeric_column(my_feature) for my_feature in features] #construct input function def 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 definition def 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 dataset input_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 dataset predictions_trainning = np.array([item["predictions"][0] for item in predictions_trainning]) #MSE mse = metrics.mean_squared_error(target_trainning, predictions_trainning)

我們能夠看出來,它的整個流程仍是同樣,只在一個地方後其餘的模型訓練過程不同,那就是選擇TensorFlow的estimator中的模型不同而已,例如上面的是一個線性的DNN,我們選擇的就是下面的DNNRegression數據結構

DNN_regressor = tf.estimator.DNNRegressor(feature_columns = construct_feature_columns(feature_trainning),
                                               optimizer = my_optimizer, hidden_units = [10,10])

注意上面定義模型的參數,它多了一個hidden_units參數,這就是用戶自定義的hidden layers的部分,若是我們的結果不理想,我們能夠適當的增長hidden_units的數量。上面的是一個線性的DNN的模型定義,那麼若是我們的是non-linear的模型,例如classification,我們如何定義呢?請看下面的代碼架構

    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模型,這裏我們能夠看出它也增長了不少參數,n_classes是說明我們的數據一共有多少個classes,默認值是2;activation_fn是選擇的relu; 這些值都是用戶根據實際狀況自定義的,我這裏的只是一個最簡單的演示。其實他還有不少不少參數能夠定義,你們本身去看文檔根據實際的狀況來定義。框架

  • 神經網絡之Keras應用

  上面我們介紹了用TensorFlow的estimator來定義和訓練神經網絡,可是在實際中有一個更增強大的框架來專門處理深度學習的問題,那就是無敵的Keras。Keras本身是一個獨立的框架,專門用來處理深度學習的相關問題,我們能夠直接下載而且導入它的組件進行應用;可是呢,無敵的TensorFlow早就爲了方便你們而提早將Keras導入到了TensorFlow的tf.keras這個模塊中了,因此你們也不須要單獨的來導入了,直接就用TensorFlow中的tf.keras模塊就能實現幾乎全部的Keras的功能。首先,我們也是來看一下用Keras最簡單的方式搭建一個DNN而且訓練這個神經網絡。dom

第一步:網絡結構搭建函數

#import keras
import tensorflow as tf
from tensorflow import keras from tensorflow.keras import layers import numpy as np ##1.build a sequential network model = keras.Sequential() #add a full-connected and dense layer model.add(layers.Dense(64,activation ='relu',input_shape=(32,))) #add an another layer with l2 regularizer model.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 regularizer model.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 initializer model.add(layers.Dense(10,activation = 'softmax')) """

首先我們初始化我們神經網絡的layers, 我們的網絡有多少的layers,我們就初始化多少個Dense layer實例。而後將這些layers按照順序的一次加入到我們的model對象中。這裏每個Dense layer我們均可以用戶自定義不少的參數,我在上面的例子中也展現了不少種例子,例若有:activation, regularizer, initializer等等不少,若是你們去看他的文檔,你們會看到更多的參數,可是在實際中,我們主要就是設置上面的例子中展現的一些參數。可是這裏有一個小細節你們必定要注意,否很容易出現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。這裏的細節很容易讓人忽略,而一旦出錯卻很難找到緣由的。另一點,input layer是不須要定義的,Keras是自動的會把我們的input layer加進去的,可是output layer是須要我們手動定義而且加上去的。因此上面的模型結構是一個input layer, 三個hidden layers和一個output layer。我們也能夠經過model.summary()的方法來檢查我們的模型結構,以下所示學習

 

 上面就是model.summary()返回的結果,它默認也沒有顯示input layer。

第二步:配置上面定義的模型結構

model.compile(
    optimizer = keras.optimizers.Adam(0.01), loss = 'mse', metrics = ['mae'])

這一步主要是給上面定義的網絡模型配置一些基本的信息,例如optimizer, loss function和metrics這些模型必要的一些信息。這裏跟我們以前講的其餘的一些基本模型都是同樣的,這裏就不在贅述了,若是不知道就看我前面的博客。

第三部: 數據準備

這部份內容呢既能夠放在我們的第一步,也能夠放在我們的網絡模型都定義好了以後,這裏我就隨機產生幾個數據當作我們的數據模型,方便我們後面內容的演示

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)

第四步:模型訓練

#trainning a model from dataset
model.fit(dataset,epochs = 10, validation_data=val_dataset)

這裏訓練數據的時候,我們的數據既能夠是numpy array也能夠是dataset,由於我我的習慣的問題,我傾向因而有dataset的數據來訓練,因此我上面的例子也是用的dataset。上面epochs的參數是說明我們的模型訓練的時候,我們一共重複我們的數據集多少次。

第五步:predict 和 evaluation

#prediction
model.predict(data)

#evaluation
model.evaluate(dataset)
  • Keras Functional APIs (save & load model)

上面只是展現瞭如何用Keras搭建而且訓練一個最簡單的神經網絡,那麼實際中我們遇到的會遇到一些其餘的需求,例如當我們的模型訓練後,我們如何保存這個模型呢?如何保存我們訓練得來的weights呢?如何加載我們存儲在本地的模型呢?如何加載我們的weights呢?這些都是我們確定會遇到的問題。那麼這些功能性的API都是如何應用呢?我們這裏就一個個的給你們介紹一下。

第一:存儲/加載 整個模型

#save a entire model
model.save("C:/Users/tangx/OneDrive/Desktop/path_to_my_model.h5")

#load a entire model model = keras.models.load_model("C:/Users/tangx/OneDrive/Desktop/path_to_my_model.h5")

上面第一步就是將我們訓練的模型(包括模型的結構和weights, bias等全部的信息)都存儲在本地的指定的位置。第二句代碼就是加載整個我們的本地的模型,固然了,這個加載後的模型也是包括了全部的信息,包括了模型結構,weights和bias全部的信息。

第二:存儲/加載 我們的weights和bias

在有些狀況下,我們只想加載我們訓練出來的weights(包括了bias啊),那麼這種狀況下,我們如何存儲呢?看下面的代碼

#only save weights
model.save_weights("C:/Users/tangx/OneDrive/Desktop/model_wights")

上面是Keras提供的將我們model的weights(包括bias)存儲在本地的方式,注意哦, 這裏只是存儲了weights哦,並無這個model的結構哦,那麼我們如何完整的加載這個模型呢?光有weights而沒有網絡結構的話但是沒有用的哦。那麼接下來看一下如何經過加載weights來加載整個模型信息呢,首先我們得知道這個weights所對應的網絡結構,而後從新定義而且初始化一個相對應的神經網絡,至關於獲取的一個「空模型「, 而後用下面的代碼將weights填充到這個「空模型」中

#restore the model's state, which requires a model with same architecture
model.load_weights("C:/Users/tangx/OneDrive/Desktop/model_wights")

這以後,至關於給我們的model填充了模型內容,從而我們的model就能夠進行正常的操做了,例如predict,evaluate等等。

第三: 存儲/加載 網絡結構和配置(serialize a model)

從上面的內容我們能夠知道,若是我們只存儲了weights的話,我們在下次加載整個模型的時候,我們還得本身從新定義而且實例化一個網絡結構和配置,而後我們才能加載我們的weights,從而讓這個模型可用。能夠實際中我們也能夠單獨的只存儲/加載這個模型的結構和配置。那麼我們如何作呢?看下面代碼演示

#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 weights
fresh_model = keras.models.model_from_json(json_string)

上面第一句代碼呢就是將我們的模型架構和配置信息轉成json的數據結構存儲起來,記住啊,這裏只存儲了網絡架構和配置信息,並不包括訓練得來的weights,這裏的過程也稱做model serialization。第二句代碼就是從我們序列化json數據格式中,加載我們的網絡結構和網絡配置信息。從而我們也能夠直接將這個fresh_model用來load_weights, 從而成爲一個完成的模型。

相關文章
相關標籤/搜索