机器学习-浅谈神经网络和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, 从而成为一个完成的模型。

相关文章
相关标签/搜索