Python机器学习17——极限学习机(ELM)

news2024/12/29 10:18:01

本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现机器学习方法。


 

背景:

极限学习机(ELM)也是学术界常用的一种机器学习算法,严格来说它应该属于神经网络,应该属于深度学习栏目,但是我这里把它放在了机器学习栏目里面,主要还是这个方法不是像别的神经网络一样方向传播误差去更新参数的。他是一个静态的模型 ,虽然它结构类似于多层感知机,只不过多层感知机的参数会随着迭代次数增加通过方向传播误差进行更新,而ELM不会,所以ELM的效果肯定是不如MLP的。

但是我也不知道为什么效果不好的模型学术界这么喜欢用......一堆论文不用MLP而是去用ELM....可能因为它不需要深度学习框架就可以搭建,而且运行速度快吧,门槛低,可能是不懂深度学习的人接触的最简单的神经网络实现的方法了。

sklearn库没有现成的接口调用,我们下面的ELM都是自定义的类,模仿sklearn的接口使用。

当然单纯的ELM由于它的权重矩阵都是静态的,效果不好,所以可以使用拟牛顿法或者别的梯度下降的方法根据误差去优化其参数矩阵,达到更好的效果。(说实话这不就是MLP嘛....)

下面会自定义ELM和优化的ELM两个类,还给出了一个基于优化的ELM结合ER回归的类。

(请注意我这里都是回归问题的ELM代码,分类问题还需要进行改动)


代码实现

原理就不多介绍了,别的文章都有,我直接给ELM的代码案例。本次使用一个回归问题,16的特征变量,响应变量是一个数值,使用ELM预测。

导入包,然后读取数据,取出X和y,我数据的最后一列就是y,然后给它划分训练集和测试集。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error,r2_score
plt.rcParams ['font.sans-serif'] ='SimHei'               #显示中文
plt.rcParams ['axes.unicode_minus']=False               #显示负号

# 加载数据
data =pd.read_csv('CS2_35的特征.csv')
X = data.iloc[:,:-1]
y = data.iloc[:,-1]

# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

标准化一下:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)
print('训练数据形状:')
print(X_train_s.shape,y_train.shape)
print('测试数据形状:')
print(X_test_s.shape,y_test.shape)

自定义ELM类 

class ELMRegressor():
    def __init__(self, n_hidden):
        self.n_hidden = n_hidden

    def fit(self, X, y):
        self.X = X
        self.y = y
        n_samples, n_features = X.shape
        self.W = np.random.randn(n_features+1, self.n_hidden)
        H = np.dot(np.concatenate((X, np.ones((n_samples, 1))), axis=1), self.W)
        H = np.maximum(H, 0)
        self.beta = np.dot(np.linalg.pinv(H), y)

    def predict(self, X):
        n_samples = X.shape[0]
        H = np.dot(np.concatenate((X, np.ones((n_samples, 1))), axis=1), self.W)
        H = np.maximum(H, 0)
        y_pred = np.dot(H, self.beta)
        return y_pred

自定义优化参数矩阵的ELM类

这里采用scipy.optimize 里面的minimize方法,使用拟牛顿法进行优化参数矩阵。

from scipy.optimize import minimize
class OP_ELMRegressor():
    def __init__(self, n_hidden):
        self.n_hidden = n_hidden

    def fit(self, X, y):
        self.X = X
        self.y = y
        n_samples, n_features = X.shape
        self.W = np.random.randn(n_features + 1, self.n_hidden)

        def loss_func(W_vec):
            W = W_vec.reshape((n_features + 1, self.n_hidden))
            H = np.dot(np.hstack((X, np.ones((n_samples, 1)))), W)
            H = np.maximum(H, 0)
            beta = np.dot(np.linalg.pinv(H), y)
            y_pred = np.dot(H, beta)
            mse = np.mean((y - y_pred) ** 2)
            return mse

        # 用拟牛顿法优化权重矩阵
        res = minimize(loss_func, self.W.ravel(), method='BFGS')
        self.W = res.x.reshape((n_features + 1, self.n_hidden))
           
        H = np.hstack((X, np.ones((n_samples, 1))))  # 添加偏置项
        H = np.dot(H, self.W)
        H = np.maximum(H, 0)
        self.beta = np.dot(np.linalg.pinv(H), y)

    def predict(self, X):
        n_samples = X.shape[0]
        H = np.hstack((X, np.ones((n_samples, 1))))
        H = np.dot(H, self.W)
        H = np.maximum(H, 0)
        y_pred = np.dot(H, self.beta)
        return y_pred

自定义优化参数矩阵的ELM结合ER回归的类

不懂什么是ER回归可以去搜一下....核心改动就是损失函数改了,不是MSE损失,而是ER损失。总之这是一种机器学习结合统计学的方法,算得上创新。

class OP_ELMRegressor_ER():
    def __init__(self, n_hidden,tau):
        self.n_hidden = n_hidden
        self.tau = tau

    def fit(self, X, y):
        self.X = X
        self.y = y
        n_samples, n_features = X.shape
        self.W = np.random.randn(n_features + 1, self.n_hidden)
        
        def loss_func(W,tau=self.tau):
            W = W.reshape((n_features + 1, self.n_hidden))
            H = np.dot(np.hstack((X, np.ones((n_samples, 1)))), W)
            H = np.maximum(H, 0)
            beta = np.dot(np.linalg.pinv(H), y)
            y_pred = np.dot(H, beta)
            loss=np.mean(np.where(np.greater(y,y_pred),np.power((y-y_pred),2)*tau,np.power((y-y_pred),2)*(1-tau)))
            return loss

        # 用拟牛顿法优化权重矩阵
        res = minimize(loss_func, self.W.ravel(), method='BFGS')
        self.W = res.x.reshape((n_features + 1, self.n_hidden))
                
        H = np.hstack((X, np.ones((n_samples, 1))))  # 添加偏置项
        H = np.dot(H, self.W)
        H = np.maximum(H, 0)
        self.beta = np.dot(np.linalg.pinv(H), y)

    def predict(self, X):
        n_samples = X.shape[0]
        H = np.hstack((X, np.ones((n_samples, 1))))
        H = np.dot(H, self.W)
        H = np.maximum(H, 0)
        y_pred = np.dot(H, self.beta)
        return y_pred

导入别的模型对比

from sklearn.linear_model import LinearRegression
from sklearn.linear_model import ElasticNet
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.svm import SVR
from sklearn.neural_network import MLPRegressor

定义评价函数,这里计算MAE,RMSE,MAPE,R2来评价预测效果。

from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error,r2_score
 
def evaluation(y_test, y_predict):
    mae = mean_absolute_error(y_test, y_predict)
    mse = mean_squared_error(y_test, y_predict)
    rmse = np.sqrt(mean_squared_error(y_test, y_predict))
    mape=(abs(y_predict -y_test)/ y_test).mean()
    r_2=r2_score(y_test, y_predict)
    return mae, rmse, mape,r_2  #mse

生成11个模型类的实例化,装入列表。

#线性回归
model1 = LinearRegression()
 
#弹性网回归
model2 = ElasticNet(alpha=0.05, l1_ratio=0.5)
 
#K近邻
model3 = KNeighborsRegressor(n_neighbors=10)
 
#决策树
model4 = DecisionTreeRegressor(random_state=77)
 
#随机森林
model5= RandomForestRegressor(n_estimators=500,  max_features=int(X_train.shape[1]/3) , random_state=0)
 
#梯度提升
model6 = GradientBoostingRegressor(n_estimators=500,random_state=123)

#支持向量机
model7 = SVR(kernel="rbf")
 
#神经网络
model8 = MLPRegressor(hidden_layer_sizes=(64,40), random_state=77, max_iter=10000)

#MLE
model9=ELMRegressor(32)

#优化MLE
model10=OP_ELMRegressor(16)

#优化MLE_ER
model11=OP_ELMRegressor_ER(16,tau=0.5)


model_list=[model1,model2,model3,model4,model5,model6,model7,model8,model9,model10,model11]
model_name=['线性回归','惩罚回归','K近邻','决策树','随机森林','梯度提升','支持向量机','神经网络','极限学习机','优化极限学习机','优化极限学习机+ER']

训练,评价,计算误差指标

df_eval=pd.DataFrame(columns=['MAE','RMSE','MAPE','R2'])
for i in range(len(model_list)):
    model_C=model_list[i]
    name=model_name[i]
    print(f'{name}正在训练...')
    model_C.fit(X_train_s, y_train)
    pred=model_C.predict(X_test_s)
    s=evaluation(y_test,pred)
    df_eval.loc[name,:]=list(s)

 查看:

df_eval

画图:

bar_width = 0.4
colors=['c', 'b', 'g', 'tomato', 'm', 'y', 'lime', 'k','orange','pink','grey','tan','purple']
fig, ax = plt.subplots(2,2,figsize=(7,5),dpi=256)
for i,col in enumerate(df_eval.columns):
    n=int(str('22')+str(i+1))
    plt.subplot(n)
    df_col=df_eval[col]
    m =np.arange(len(df_col))
    
    #hatch=['-','/','+','x'],
    plt.bar(x=m,height=df_col.to_numpy(),width=bar_width,color=colors)
    
    #plt.xlabel('Methods',fontsize=12)
    names=df_col.index
    plt.xticks(range(len(df_col)),names,fontsize=8)
    plt.xticks(rotation=40)
    
    if col=='R2':
        plt.ylabel(r'$R^{2}$',fontsize=14)
    else:
        plt.ylabel(col,fontsize=14)
plt.tight_layout()
#plt.savefig('柱状图.jpg',dpi=512)
plt.show()

 从效果上来看,这个数据集的X对y的解释能力还是很强的,线性回归的拟合优度都到了99%,所以基本模型都差不多是这个表现。单纯的ELM的表现比线性回归还差,但是用拟牛顿法优化过后效果还不错,加了ER效果也是差不多的。ER还有分位数tau这个参数可以改,说不定能出更好的效果。

整体来说是一个效果一般的机器学习模型,但是原理简单,可以很容易去改动和创新,然后发文章,所以学术界都喜欢用这个吧。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/389730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C/C++开发,无可避免的多线程(篇四).线程与函数的奇妙碰撞

一、函数、函数指针及函数对象 1.1 函数 函数(function)是把一个语句序列(函数体, function body)关联到一个名字和零或更多个函数形参(function parameter)的列表的 C 实体,可以通过返回或者抛…

MongoDB分片教程

一、概述分片是一种将数据分布在多个 机器。MongoDB使用分片来支持具有非常大数据的部署 集和高吞吐量操作。具有大型数据集或高吞吐量应用程序的数据库系统可以 挑战单个服务器的容量。例如,高查询率可以 耗尽服务器的 CPU 容量。工作集大小大于 系统的 RAM 会给磁…

初学者的第一个Linux驱动

软件环境:Ubuntu20.04 Linux内核源码:3.4.39 硬件环境:GEC6818 什么是驱动?简单来说就是让硬件工作起来的程序代码。 Linux驱动模块加载有两种方式: 1、把写好的驱动代码直接编译进内核。 2、把写好的驱动代码编…

Linux24 -- tcp相关概念、多个客户端链接服务端代码

一、tcp相关概念 tcp协议特点:面向连接的、可靠的、流式服务 建立链接:三次握手,发送 SYN 断开链接;四次挥手,发送 FIN tcp、udp都同属于传输层,在网络层使用ip协议,都要将数据交给IP协议&am…

零拷贝技术-内核源码剖析

在网络编程中,如果我们想要提供文件传输的功能,最简单的方法就是用read将数据从磁盘上的文件中读取出来,再将其用write写入到socket中,通过网络协议发送给客户端。ssize_t read(int fd, void *buf, size_t count); ssize_t write(…

学习记录---latent code 潜在编码

文章目录参考文献1. 什么是潜在编码?2.什么是潜在空间?3.同类潜在编码的相似性4.潜在编码的应用4.1 Antoencoders4.2 Generative models5.结论个人学习总结,持续更新中……参考文献 [1] 快速理解深度学习中的latent code潜在编码 1. 什么是…

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战1. 与408关联解析及本节内容介绍1 本节内容介绍2. 单链表的删除操作实战3. 单链表真题解读与解题设计1 题目解读2 解题设计第一阶段:双指针找中间结点第二阶段:原地逆置第三阶段&#xff…

ubuntu16.04 python代码自启动和可执行文件自启动

1 python代码自启动 参考 https://blog.csdn.net/qq_38288618/article/details/104096606 准备好python文件 test.py import time c1 while 1:time.sleep(1)cc1print(c)运行 sudo chmod 777 test.py python3 test.py准备run.sh 文件 #!/bin/bash gnome-terminal -x bash -…

【Spring6】IoC容器之基于XML管理Bean

3、容器:IoC IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。 Spring 通过 IoC 容…

C语言学习笔记——指针(初阶)

前言 指针可以说是C语言基础语法中最难的理解的知识之一,很多新手(包括我)刚接触指针时都觉得很难。在我之前发布的笔记中都穿插运用了指针,但是我一直没有专门出一期指针的笔记,这是因为我确实还有些细节至今还不太清…

STM32之关门狗

看门狗介绍在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入…

vue3+rust个人博客建站日记5-所有界面

没有数据的前端,是没有灵魂的。明明标题是vue3 rust ,但日记撰写至今,似乎只有第一篇提及了Rust,这可不行。是时候一股作气,完成大部分页面绘制工作了! 最后再说一次,时间要加速了。 ——普奇神…

EPICS S7nodave手册

第一章:介绍 本手册分为6章(不算次介绍部分)。第一章介绍s7nodave用于EPICS的设备支持的概念和特新。第二章描述启动一个使用s7nodave的IOC项目所需要的几步。第三章描述s7nodave支持的IOC shell命令。之后,第四章解释s7nodave支持的各种记录类型。最后…

【算法】期末复盘,酒店住宿问题——勿向思想僵化前进

文章目录前言题目描述卡在哪里代码(C)前言 省流:一个人也可以住双人间,如果便宜的话。 害!尚正值青春年华,黄金岁月,小脑瓜子就已经不灵光咯。好在我在考试的最后一分钟还是成功通过了这题&am…

Jetpack Compose 中的 CompositionLocal

要在可组合函数之间共享数据时,可以通过参数传递显式地调用,这通常是最简单和最好的方式。 但随着参数越来越多,组件也越来越多,并且有些数据还需要保持私有性,这时这种方式就会显得很繁琐臃肿,难以维护。…

vscode插件推荐

文章目录前言一、vscode插件推荐?1、 Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code2、Auto Close Tag3、Auto Import3、Error Lens4、vscode-icons5、ES7 React/Redux/React-Native snippets6、GitLens — Git supercharged7、JavaScript…

【FPGA】Verilog:时序电路应用 | 序列发生器 | 序列检测器

前言:本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例:序列发生器与序列检测器 ​ 功能特性: 采用 Xilinx Artix-7 XC7A35T芯片 配置方式:USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度 存储器…

车道线检测CondLaneNet论文和源码解读

CondLaneNet: a Top-to-down Lane Detection Framework Based on Conditional Convolution Paper:https://arxiv.org/pdf/2105.05003.pdf code:GitHub - aliyun/conditional-lane-detection 论文解读: 一、摘要 这项工作作为车道线检测任…

js垃圾回收机制

内存的生命周期 ]S环境中分配的内存,一般有如下生命周期 1.内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存 2.内存使用:即读写内存,也就是使用变量、函数等 3.内存回收: 使用完毕,由垃圾回收器自动回收不再…

MySQL实战解析底层---事务到底是隔离的还是不隔离的

目录 前言 “快照”在 MVCC 里是怎么工作的? 更新逻辑 前言 讲事务隔离级别的时候提到过,如果是可重复读隔离级别,事务 T 启动的时候会创建一个视图 read-view之后事务 T 执行期间,即使有其他事务修改了数据,事务 T…