前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实现深度神经网络只需60行代码

实现深度神经网络只需60行代码

作者头像
商业新知
修改2019-07-26 17:43:19
6210
修改2019-07-26 17:43:19
举报
文章被收录于专栏:AI人工智能

0 1 准备数据集

采用的数据集是sklearn中的breast cancer数据集,30维特征,569个样本。训练前进行MinMax标准化缩放至[0,1]区间。按照75/25比例划分成训练集和验证集。

# 获取数据集

import numpy as npimport pandas as pdfrom sklearn import datasetsfrom sklearn import preprocessingfrom sklearn.model_selection import train_test_splitbreast = datasets.load_breast_cancer()scaler = preprocessing.MinMaxScaler()data = scaler.fit_transform(breast['data'])target = breast['target']X_train,X_test,y_train,y_test = train_test_split(data,target)

0 2 模型结构图

0 3 正反传播公式

0 4 NN实现代码

import numpy as np

import pandas as pd#定义激活函数ReLu = lambda z:np.maximum(0.0,z)d_ReLu = lambda z:np.where(z<0,0,1)LeakyReLu = lambda z:np.maximum(0.01*z,z)d_LeakyReLu = lambda z:np.where(z<0,0.01,1)Sigmoid = lambda z:1/(1+np.exp(-z))d_Sigmoid = lambda z: Sigmoid(z)*(1-Sigmoid(z))  #d_Sigmoid = a(1-a)Tanh = np.tanhd_Tanh = lambda z:1 - Tanh(z)**2#d_Tanh = 1 - a**2classNNClassifier(object):def__init__(self,n = [np.nan,5,5,1],alpha = 0.1,ITERNUM = 50000, gfunc = 'ReLu'):        self.n = n #各层节点数        self.gfunc = gfunc #隐藏层激活函数        self.alpha,self.ITERNUM = alpha,ITERNUM        self.dfJ = pd.DataFrame(data = np.zeros((ITERNUM,1)),columns = ['J'])        self.W,self.b = np.nan,np.nan# 确定各层激活函数        self.g = [eval(self.gfunc) for i in range(len(n))];        self.g[-1] = Sigmoid;self.g[0] = np.nan# 确定隐藏层激活函数的导数        self.d_gfunc = eval('d_' + self.gfunc)deffit(self,X_train,y_train):        X,Y = X_train.T,y_train.reshape(1,-1)        m = X.shape[1] #样本个数        n = self.n; n[0] = X.shape[0] # 各层节点数量# 节点值和参数初始化        A = [np.zeros((ni,m)) for ni in n];A[0] = X #各层节点输出值初始化        Z = [np.zeros((ni,m)) for ni in n];Z[0] = np.nan #各层节点中间值初始化        W = [np.nan] + [np.random.randn(n[i],n[i-1]) * 0.01for i in range(1,len(n))] #各层系数参数        b = [np.zeros((ni,1)) for ni in n];b[0] = np.nan #n各层偏置参数# 导数初始化        dA = [np.zeros(Ai.shape) for Ai in A]        dZ = [np.zeros(Ai.shape) for Ai in A]        dW = [np.zeros(Wi.shape) if isinstance(Wi,np.ndarray) else np.nan for Wi in W]           db = [np.zeros(bi.shape) if isinstance(bi,np.ndarray) else np.nan for bi in b] for k in range(self.ITERNUM):# ---------正向传播 ----------for i in range(1,len(n)):                Z[i] = np.dot(W[i],A[i-1]) + b[i]                A[i] = self.g[i](Z[i])            J = (1/m) * np.sum(- Y*np.log(A[len(n)-1]) -(1-Y)*np.log(1-A[len(n)-1]))            self.dfJ.loc[k]['J']= J# ----------反向传播 ---------            hmax = len(n) - 1            dA[hmax] = 1/m*(-Y/A[hmax] + (1-Y)/(1-A[hmax]))            dZ[hmax] = 1/m*(A[hmax]-Y)            dW[hmax] = np.dot(dZ[hmax],A[hmax-1].T)            db[hmax] = np.dot(dZ[hmax],np.ones((m,1)))for i in range(len(n)-2,0,-1):                dA[i] = np.dot(W[i+1].T,dZ[i+1])                dZ[i] = dA[i]* self.d_gfunc(Z[i])                dW[i] = np.dot(dZ[i],A[i-1].T)                db[i] = np.dot(dZ[i],np.ones((m,1)))#-----------梯度下降 ---------for i in range(1,len(n)):                W[i] = W[i] - self.alpha*dW[i]                 b[i] = b[i] - self.alpha*db[i]# 显示进度if (k+1)%1000 == 0:                print('progress rate:{}/{}'.format(k+1,self.ITERNUM),end = 'r')        self.W,self.b = W,bdefpredict_prob(self,X_test):# ---------正向传播 ----------        W,b = self.W,self.b        Ai = X_test.Tfor i in range(1,len(self.n)):            Zi = np.dot(W[i],Ai) + b[i]            Ai = self.g[i](Zi)return(Ai.reshape(-1))defpredict(self,X_test):        Y_prob = self.predict_prob(X_test)        Y_test = Y_prob.copy()        Y_test[Y_prob>=0.5] = 1        Y_test[Y_prob< 0.5] = 0return(Y_test) 

0 5 单隐层神经网络

设置1个隐藏层,隐藏层节点数为5,隐藏层使用Sigmoid激活函数。

# 采用Sigmoid激活函数

NN = NNClassifier(n = [np.nan,5,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'Sigmoid')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)

roc_auc_score(list(y_test),list(Y_prob))

隐藏层使用Tanh激活函数。

# 采用 Tanh激活函数

NN = NNClassifier(n = [np.nan,5,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'Tanh')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)roc_auc_score(list(y_test),list(Y_prob))

隐藏层使用ReLu激活函数。

# 采用 ReLu激活函数

NN = NNClassifier(n = [np.nan,5,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'ReLu')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)roc_auc_score(list(y_test),list(Y_prob))

隐藏层使用LeakyReLu激活函数。

# 采用 LeakyReLu激活函数

NN = NNClassifier(n = [np.nan,5,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'LeakyReLu')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)roc_auc_score(list(y_test),list(Y_prob))

以上试验似乎表明,在当前的数据集上,隐藏层采用ReLu激活函数是一个最好的选择,AUC最高得分为0.99958。

0 6 双隐层神经网络

设置2个隐藏层,隐藏层节点数都为5,隐藏层都使用ReLu激活函数。

# 设置两个隐藏层,采用ReLu激活函数

NN = NNClassifier(n = [np.nan,5,5,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'ReLu')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)roc_auc_score(list(y_test),list(Y_prob))

AUC得分0.99874比采用单隐藏层的最优得分0.99958有所降低,可能是模型复杂度过高,我们尝试减少隐藏层节点的个数至3以降低模型复杂度。

# 双隐藏层,隐藏层节点数为3

NN = NNClassifier(n = [np.nan,3,3,1],alpha = 0.02,                 ITERNUM = 200000, gfunc = 'ReLu')NN.fit(X_train,y_train)# 绘制目标函数迭代曲线%matplotlib inlineNN.dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = NN.predict_prob(X_test)roc_auc_score(list(y_test),list(Y_prob))

AUC得分0.99979,又有所提高。

和sklearn中自带的神经网络分类器进行对比。

# 和sklearn中的模型对比

from sklearn.neural_network import MLPClassifier# 第一隐藏层神经元个数为3,第二隐藏层神经元个数为3MLPClf = MLPClassifier(hidden_layer_sizes=(3,3),max_iter=200000,activation='relu')MLPClf.fit(X_train,y_train)# 绘制目标函数迭代曲线dfJ = pd.DataFrame(data = np.array(MLPClf.loss_curve_),columns = ['J'])dfJ.plot(figsize = (12,8))# 测试在验证集的auc得分from sklearn.metrics import roc_auc_scoreY_prob = MLPClf.predict_proba(X_test)[:,1]roc_auc_score(list(y_test),list(Y_prob))

以上试验表明,针对当前数据数据集,选择ReLu激活函数,采用双隐藏层,每个隐藏层节点数设置为3是一个不错的选择,AUC得分为0.99979。该得分高于采用CV交叉验证优化超参数后的逻辑回归模型的0.99897的AUC得分。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档