【小项目-2】极限学习机的理解及代码实现

理论参考文章文章
项目参考文章
我自己的项目代码

自己的理解和总结:

对H随机赋值然后求\beta来达到最小化代价函数的目的,加快了运算速度。

一、数学原理

对于一个单隐层神经网络,结构如下图:


单隐层神经网络

极限学习机的网络训练模型

假设有m个输入节点,M个隐藏神经元,N个输出节点。

  • 前向传播的详细矩阵推导

第i个神经元的输入为:(m项输入乘以对应权重矩阵)
w_{1i}x_{i1} + w_{2i}x_{i2}+...+w_{mi}x_{im}
W_i\cdot X_i
极限学习机的网络训练模型可用数学表达式表示如下:(N个输出节点的值)
\sum_{i=1}^{M}\beta _{i}g(W_i\cdot X_i+b_i) = o_j, j=1,2,...,N

  • 基于代价函数最小,优化神经网络参数Wb
    极限学习机的优化过程就是寻求最优解使得损失函数最小的过程。
    令:
    H(w_1,...,w_M, b_1,...,b_M, x_1,...,x_N)={\begin{bmatrix} g(w_1x_1+b_1) & \cdots & g(w_Mx_1+b_M)\\ \vdots & & \vdots \\g(w_1x_N+b_1) & \cdots & g(w_Mx_N+b_M) \end{bmatrix}}_{N \times M}
    则:
    最优的情况为:
    H\beta = T
    即:
    \min E\left ( S, \beta \right ) =\min_{w_i,b_i, \beta } \begin{Vmatrix}H(w_1,...,w_M, b_1,...,b_M, x_1,...,x_N)\beta -T\end{Vmatrix}
    其中表示S = (w_i,b_i, i =1,2,...,M)表示网络的输入权值和隐藏层节点阈值,H表示网络关于样本的隐藏层输出矩阵,\beta表示输出权值矩阵,T表示样本集的目标值矩阵。

\beta ={\begin{bmatrix}\beta_1^T\\ \vdots \\ \beta_M^T\\\end{bmatrix}}_{M\times N}

T ={\begin{bmatrix}t_1^T\\ \vdots \\ t_{N}^T\\ \end{bmatrix}}_{n\times N}

  • 训练过程
    这里分析了为什么极限学习速度快。

在传统的单层神经网络中,input weight不可以随机产生,必须在求解过程中和output weight一起进行update,这一过程必须运用iteration的方式进行,运算时间较长。ELM证明了input weight随机产生并且在之后的计算中固定也可以达到同样的目的,所以在求解过程中只需要求output weight。 这样就可以运用简单的矩阵运算一步求出标准解而大大提高运算效率。

极限学习机算法的训练过程可归结为一个非线性优化问题。
当隐藏层节点的激活函数可微时,网络的输入权值和隐藏层节点阈值可以随机赋值,此时矩阵H是一个常数矩阵,极限学习机的学习过程可等价位求取线性系统H\beta=T最小范数的最小二乘解\hat \beta,其计算公式为:
\hat \beta = H^\dagger T
H^\dagger是矩阵H的广义逆,可以通过奇异值分解求得。
通过这种方式就可以计算出学习网络的输出权值。
同迭代算法相比,极限学习机及大地提高了网络的泛化能力和学习速度。

为什么”当隐藏层节点的激活函数可微时,网络的输入权值和隐藏层节点阈值可以随机赋值“?
我自己的理解是,激活函数都得可微,这样才能进行反向传播吧。(虽然这里没有涉及反向传播)

下面我们从具体的高维数据来分析:

# 计算h
x.shape 
(3647, 5)
b.shape
(3647, 90)
w.shape
(5, 90)

h = sigmoid(np.dot(x, w) + b)
(3647, 90)
# h为隐神经元的输出
H_.shape
(90, 3647)
T.shape
(3647, 1)
beta.shape
(90, 1)

体会如下:

  • w和x的点乘把维度项给抵消掉了:不同的输出x与同一个神经元连接的权重w是相同的
  • beta并不是单纯地相乘,也是相乘之后再相加,起到了点乘的效果

二、评价/与Deep learning的区别:

参考知乎链接

  • ELM最初只是一种特殊单隐层神经网络,有解析解,因此简单、快速;而深度学习需要参数更新,样本需求大、速度慢;
  • 线性和非线性的区别

    DL具有明确的‘学习’意味或者说是非线性特征抽取的能力,因为它可以根据数据和任务调整参数,使得DL在诸多场景下都适用;尽管ELM也是学习模型,但它本质上是线性的(至少答主是这么理解),看它的优化函数,本质上就是岭回归,是线性的。
    优化函数
  • 性能上,不可否认ELM在低维度简单的小数据集上效果是要略优于DL的,但在复杂数据上,如语音、图像上,DL依旧是独领风骚。另外,ELM不能或者很难作生成模型

三、项目实现

ELM实现思路:
ELM的实现方法

下面用MNIST dataset来训练网络实现手写数字的分类。

数据准备
  • 导入必要库
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import MinMaxScaler
  • 读入dataset
train = pd.read_csv('mnist_train.csv')
test = pd.read_csv('mnist_test.csv')
  • 用sckikit-learn包中的MinMaxScaler归一化数据到(0,1)之间,然后用OneHotEncoder把tagets转化成one-hot encoding format.
  • MinMaxScaler:数据(x)按照最小值中心化后,再按极差(最大值 - 最小值)缩放,数据移动了最小值个单位,并且会被收敛到[0,1]之间。
  • StandardScaler()(更常用):数据(x)按均值(μ)中心化后,再按标准差(σ)缩放,数据就会服从为均值为0,方差为1的正态分布(即标准正态分布)
  • scaler.fit_transform这个函数计算数据的均值和方差,并基于此进行数据转化
  • onehotencoder:对target/label进行onehot编码。
    对类别变量进行“二进制化”操作,然后将其作为模型训练的特征。
    关于one hot编码的讲解
onehotencoder = OneHotEncoder(categories='auto')
scaler = MinMaxScaler()
X_train = scaler.fit_transform(train.values[:,1:])
y_train = onehotencoder.fit_transform(train.values[:,:1]).toarray()
X_test = scaler.fit_transform(test.values[:,1:])
y_test = onehotencoder.fit_transform(test.values[:,:1]).toarray()
初始化网络

需要确定如下参数:

  1. The size of the input layer, which is the number of input features
  2. Number of hidden neurons
  3. Input to hidden weights
  4. Hidden layer activation function

输入层的尺寸取决于the number of input features of the dataset

input_size = X_train.shape[1]

隐藏神经元数目初始化为1000

hidden_size = 1000

输入权重和偏差biases的基于高斯分布的初始化

input_weights = np.random.normal(size=[input_size,hidden_size])
biases = np.random.normal(size=[hidden_size])

激活函数设置为Relu函数

def relu(x):
   return np.maximum(x, 0, x)
进一步的计算

计算输出权重\beta

$\beta$的计算公式

公式中, H (dagger) is the Moore–Penrose generalized inverse of matrix H, and T is our target.
先计算H:

def hidden_nodes(X):
    G = np.dot(X, input_weights)
    G = G + biases
    H = relu(G)
    return H

再计算\beta

output_weights = np.dot(pinv2(hidden_nodes(X_train)), y_train)

pinv这个函数就可以计算H的逆,进而计算H的逆和T的点乘。

模型测试
def predict(X):
    out = hidden_nodes(X)
    out = np.dot(out, output_weights)
    return out
prediction = predict(X_test)
correct = 0
total = X_test.shape[0]

for i in range(total):
    predicted = np.argmax(prediction[i])
    actual = np.argmax(y_test[i])
    correct += 1 if predicted == actual else 0
accuracy = correct/total
print('Accuracy for ', hidden_size, ' hidden nodes: ', accuracy)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容