自组织特征图SOFM网络的实现
这里直接给出Qt代码段和演示结果。
理论部分请移步另一位博主的 自组织特征图(SOFM)详解_datamonday的博客-CSDN博客_sofm算法
算法基于 Martin H. Hagan 的《神经网络设计》 第十四章竞争网络实现。其中按照原书,使用相关性(Wp)而不是距离(||W-P||)作为获胜判定。以后将在学习向量量化(LVQ)网络中使用距离
算法改进包括:
引入逐渐变小的学习步长
引入墨西哥草帽函数实现“加强中心/抑制周围”
参考代码 AANN_sofm::initNeighborMatrix_MexicoStrawHat(int N)
引入良心变数(conscience),并限制良心变数使用的频率
使用胜出训练参数和需要调整的W(i)之间的距离来决定学习步长a,否则在实践中会发现向量很难收敛在训练数据集形成的曲面上。
(auto a = (P.transpose() - m_layer.W.row(maxIndex)).squaredNorm()/(0.01+m_layer.W.row(maxIndex).squaredNorm());)
AANN_sofm.h 文件
#ifndef AANN_SOFM_H
#define AANN_SOFM_H#include <list>
#include <vector>
#include <Eigen/Dense>
#include "QEigenExt.h"
using namespace Eigen;#include "AANN_instar.h"
/**** 自联想神经网络(Auto-Associative Neural Network , 缩写为AANN)* 是1987年Ballard提出的,其网络原型是一种具有对称拓扑结构的五层前馈传递网络,* AANN 应用到数据检验问题时具有比较明显的物理意义。是BP神经网络的一种特殊情形。* 其特点是有对称拓扑结构,即输出量等于输入量。*/
class AANN_sofm
{
public:AANN_sofm();public:
// int GetLayerNum() const;
// bool AppendLayer(AANN_LAYER_PARAM_F layer);virtual bool train( const Eigen::VectorXf &P, int N );virtual bool calc( const Eigen::VectorXf &P, Eigen::VectorXf *A = NULL );float getAlpha( ) const;float getGamma( ) const;long getRound( ) const;void setAlpha( const float alpha);void setGamma( const float gamma);bool setNeighborMatrix( const MatrixXf neighbors );bool initNeighborMatrix( int N, int type );bool initNeighborMatrix_MexicoStrawHat( int N );bool initNeighborMatrix_Sombrero( int N );const MatrixXf getWMatrix() const;
private:void init();private:
// AANN_LAYER_LIST_F m_layerList;AANN_LAYER_PARAM_F m_layer;float m_alpha;float m_gamma;long m_round;};#endif // AANN_SOFM_H
AANN_sofm.cpp文件
#include "AANN_sofm.h"#include "activation.h"
#include <iostream>
#include <time.h>
#include <stdio.h>AANN_sofm::AANN_sofm()
{m_alpha = 0.5f;m_gamma = 0.5f;init();
}void AANN_sofm::init()
{m_layer.maxB = -1;m_layer.func = hardlim;m_round = 0;
}float AANN_sofm::getAlpha( ) const
{return m_alpha;
}float AANN_sofm::getGamma( ) const
{return m_gamma;
}long AANN_sofm::getRound( ) const
{return m_round;
}void AANN_sofm::setAlpha( const float alpha)
{m_alpha = alpha;
}void AANN_sofm::setGamma( const float gamma)
{m_gamma = gamma;
}bool AANN_sofm::setNeighborMatrix( const MatrixXf neighbors )
{if( !neighbors.size() || neighbors.rows() != neighbors.cols()){return false;}m_layer.Neighbors = neighbors;qDebug() << QString( " --------------- neighbors %1 x %2 ---------------" ).arg(neighbors.rows()).arg(neighbors.cols());for(int row=0; row<neighbors.rows(); row++ ){VectorXf r = neighbors.row(row);qDebug() << " " << r;}return true;
}/*** @brief AANN_sofm::initNeighborMatrix* set neighbor matris for SOFM* @param eMat* EX: the neighbor pointers about 7 will be 2,6,8,12* All others will be like so* 0 1 2 3 4* ^* 5 6 < 7 > 8 9* v* 10 11 12 13 14* 15 16 17 18 19* 20 21 22 23 24** Then, neighbor Matrix will be* 0 1 2 3 4 5 6 7 8 9 10 11 12 ..... 20 21 22 23 24* +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+* 0 | 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 1 | 1 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 2 | 0 1 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 3 | 0 0 1 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 4 | 0 0 0 1 1 0 0 0 0 1 0 ..... 0 0 0 0 0* 5 | 1 0 0 0 0 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 6 | 0 1 0 0 0 1 1 1 0 0 0 1 0 ..... 0 0 0 0 0* 7 | 0 1 0 0 0 1* 8 | 0 1 0 0 0* 9 | 0 1 0 0* 10 | 0 1 0* . | 0 1* . |* . |* . |* . |* 22 | 0 0 0 0 0 0 0 0 0 0 0 0 0 ... 0 1 1 1 0* 23 | 0 0 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 1 1 1* 24 | 0 0 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 1 1*/
bool AANN_sofm::initNeighborMatrix( int N, int type = 0 )
{Q_UNUSED( type );if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = MatrixXf::Identity( N*N, N*N ) - MatrixXf::Ones( N*N, N*N )/((N+4)*(N+4));for( int row = 0; row < N*N; row++){int x = row%N;int y = row/N;if( (y+N-1)%N < y ){neighbor( ((y+N-1)%N)*N+x, row ) = 1.f/((N+1)*(N+1));}if( (y+1)%N >y ){neighbor( ((y+1)%N)*N+x, row ) = 1.f/((N+1)*(N+1));}if( (x+N-1)%N < x ){neighbor( row, y*N+(x+N-1)%N ) = 1.f/((N+1)*(N+1));}if( (x+1)%N > x ) {neighbor( row, y*N+(x+1)%N ) = 1.f/((N+1)*(N+1));}}return setNeighborMatrix( neighbor );
}bool AANN_sofm::initNeighborMatrix_MexicoStrawHat( int N )
{if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = MatrixXf::Identity( N*N, N*N );for( int row = 0; row < N*N; row++)for( int col = row+1; col < N*N; col++){int dx = row%N - col%N;int dy = row/N - col/N;float d1 = 1+dx*dx+dy*dy;float d2 = (dx*dx+dy*dy)*d1*d1;neighbor( row, col ) = neighbor( col, row ) = (1.0f/d2 - 0.07f)/d1;}return setNeighborMatrix( neighbor );
}/*** @brief AANN_sofm::initNeighborMatrix_Sombrero* refer to https://baike.baidu.com/item/Sombrero%20function/16550687* @return*/
bool AANN_sofm::initNeighborMatrix_Sombrero( int N )
{if( N <= 0 || N > 10000 ){return false;}MatrixXf neighbor = 0.98*MatrixXf::Identity( N*N, N*N );for( int row = 0; row < N*N; row++)for( int col = row+1; col < N*N; col++){int dx = row%N - col%N;int dy = row/N - col/N;float d2 = dx*dx+dy*dy;float d1 = sqrt( d2 );float d4 = exp(2*d2);
// float cc = cos( (3.14f/2-0.1)*d1 );
// float dd = cc/d4;neighbor( row, col ) = neighbor( col, row ) = cos( (3.14159/2-0.01)*d1 )/d4;}return setNeighborMatrix( neighbor );
}const MatrixXf AANN_sofm::getWMatrix() const
{return m_layer.W;
}
/*** @brief AANN_sofm::train* @param P measured vector : 可度量特征信息:如形状,味道,温度,颜色,重量等* @param T 感知的结果,或期望的结果* @return*/
bool AANN_sofm::train( const Eigen::VectorXf &P, int S )
{const int R = P.rows();/* return false if input Dim is different */if( S <= 0 ){return false;}/* return false if input Dim is different */if( ( m_layer.W.cols() > 0 ) && ( m_layer.W.cols() != R ) ){return false;}/* return false if output Dim is different */if( ( m_layer.W.rows() > 0 ) && ( m_layer.W.rows() != S ) ){return false;}if( m_layer.Neighbors.size() && (m_layer.Neighbors.rows() != S || m_layer.Neighbors.cols() != S )){return false;}if( S != m_layer.W.rows() || R != m_layer.W.cols() ){srand( time(NULL) );m_layer.W = MatrixXf::Random( S, R );m_layer.Conscience = VectorXf::Ones( S );}int maxIndex;m_layer.N = (m_layer.W * P).array() + R;/*** @brief round_mask* 随着训练次数增长,应用良心的间隔越来越大,但总是有机会使用* M = 3 时* m_round : 0~7 8~15 16~31 32~63 ... 2^(n+3) ~ 2^(n+3)-1* N : 0 1 2 4 ... 2^n* round_mask : 0x...FFFFF 1 3 7 ... (2^(n+1))-1* apply conscience : 8 x 8 x 8 x 8 x ... 8 x* M = 6 时* m_round : 0~63 64~127 128~255 256~511 ... 2^(n+6) ~ 2^(n+6)-1* N : 0 1 2 4 ... 2^n* round_mask : 0x...FFFFF 1 3 7 ... (2^(n+1))-1* apply conscience : 64 x 64 x 64 x 64 x ... 64 x** 应用良心的频率随 M 的增加而呈指数增加,测试中 M=3 能得到比较好的性能*/static int round_mask = 1;int N = m_round >> 3;if( 0 == ( N&(N-1) ) ){round_mask = (N<<1)-1; // 0,1,2,4,8,16,...}if( 0 == ( m_round & round_mask ) ){(m_layer.N.array() * m_layer.Conscience.array()).maxCoeff(&maxIndex);} else {m_layer.N.maxCoeff(&maxIndex);}m_layer.A = VectorXf::Zero(S);m_layer.A[maxIndex] = 1;m_layer.Conscience = m_layer.Conscience.array()/(1+m_layer.A.array()).array();m_layer.Conscience.normalize();VectorXf vecA;if( m_layer.Neighbors.rows() == S ){
// vecA = ( m_layer.Neighbors * m_layer.A ).unaryExpr(std::ref(satlin<float>));vecA = (m_layer.Neighbors * m_layer.A).normalized();} else {vecA = m_layer.A;}/** delta W = W(q) - W(q-1) = alpha * A(q) * P(q) - gamma * A(q).diagonal * W(q-1)*/auto a = (P.transpose() - m_layer.W.row(maxIndex)).squaredNorm()/(0.01+m_layer.W.row(maxIndex).squaredNorm());a = fmin( 1.0, fmax( a, m_alpha ));m_layer.deltaW = a * vecA * P.transpose() - a * vecA.asDiagonal() * m_layer.W;m_layer.W = (m_layer.W + m_layer.deltaW);//.rowwise().normalized();m_round++;return true;
}/*** @brief AANN_sofm::calc* @param P measured vector : 可度量特征信息:如形状,味道,温度,颜色,重量等* @return*/
bool AANN_sofm::calc( const Eigen::VectorXf &P, Eigen::VectorXf *A )
{AANN_LAYER_PARAM_F layer = m_layer;Eigen::VectorXf e;const int R = P.rows();/* return false if input Dim is different */if( ( m_layer.W.cols() <= 0 ) || ( m_layer.W.cols() != R ) ){qWarning() << QString( __FUNCTION__ " : Error! input dim is different : expect %1, but input data is %2 " ).arg(m_layer.W.cols()).arg( R );return false;}qDebug() << __FUNCTION__ " --- CALC -----------------------";qDebug() << __FUNCTION__ " P = " << P.eval() ;m_layer.A = (m_layer.W * P).unaryExpr(std::ref(m_layer.func));qDebug() << __FUNCTION__ " A = " << m_layer.A;if( A ) { *A = m_layer.A; }return true;
}
线程执行代码段:
void DataWorker::on_start()
{for(int k = 0; !m_bUserQuit && (k < 100000); k++ ) // while( false == m_bUserQuit ){updateNnData();QThread::msleep(10);}
}#define N 3void DataWorker::reset()
{m_sofm.initNeighborMatrix_Sombrero(N);
}void DataWorker::updateNnData( )
{QMutexLocker locker( &m_nnLocker );float r = sqrt(m_sofm.getRound()) ;float alpha = (r+500.0f)/( 100*r+1000.0f);m_sofm.setAlpha( alpha );m_sofm.setGamma( alpha );#define PI 3.14159265358979{float a = - acos(sqrt( (rand() % 257) / 256.0001)); // -3.14 * (rand() % 256) / 512.0;float b = PI * (rand() % 12345) / 1000.0;VectorXf P(3);P << cos(a)*sin(b), sin(a), cos(a)*cos(b);if(m_trainSetModel && ( m_sofm.getRound() < 10000) ){
// WData d(cos(a)*sin(b), cos(a)*cos(b), sin(a));m_trainSetModel->append( WData(P[0],P[1],P[2]));m_trainSetModel->dataChanged( m_trainSetModel->index(0,0), m_trainSetModel->index(-1,-1));}m_sofm.train( P, N*N );}m_dataModel->update(m_sofm.getWMatrix());}
以下是36点在半球形中的演示结果
以下是9点在半球形中的演示结果。看得出,用距离来决定学习步长在这时造成了结果的发散
演示代码
自组织特征图SOFM网络的实现相关推荐
- 基因表达聚类分析之初探SOM - 自组织特征图
之前的培训有老师提出要做SOM分析,最后卡在code plot只能出segment plot却出不来line plot.查了下,没看到解决方案.今天看了下源码,设置了一个参数,得到趋势图.也顺便学习了 ...
- som神经网络聚类简单例子_基因表达聚类分析之初探SOM - 自组织特征图
之前的培训有老师提出要做SOM分析,最后卡在code plot只能出segment plot却出不来line plot.查了下,没看到解决方案.今天看了下源码,设置了一个参数,得到趋势图.也顺便学习了 ...
- FPN:特征图金字塔网络
1. 论文简介 论文名:Feature Pyramid Networks for Object Detection 论文地址 :FPN 论文作者:Tsung-Yi Lin, Piotr Dollar, ...
- FPN(特征图金字塔网络)理论基础与具体实现
论文地址:Feature Pyramid Networks for Object Detection 项目地址:FPN_pytorch 0x00 前言 我们在做目标检测和超分辨率重建等问题的时候,我们 ...
- 机器学习 竞争神经网络与自组织特征映射神经网络(SOFM)
本文按照 案例-分析-代码-原理 四段式进行介绍,为便于有一定理论基础的童鞋进行学习,将原理以链接其他博客的形式给出,有兴趣的童鞋可以跳转进行学习和推敲. [案例介绍]利用竞争神经网络和自组织特征隐射 ...
- 卷积神经网络特征图可视化及其意义
文章目录 特征图可视化方法 1. tensor->numpy->plt.save 2. register_forward_pre_hook函数实现特征图获取 3. 反卷积可视化 特征图可视 ...
- 卷积神经网络的特征图可视化
原图: Keras代码: from keras.models import Sequential from keras.layers.convolutional import Convolution2 ...
- 利用ANN作图——自组织特征映射网络(SOFM)探究及实现
利用ANN作图--自组织特征映射网络(SOFM)探究及实现 在研究生的<人工智能>课堂上学习了利用人工神经网络(ANN)解决问题的基本思想与方法,在学习了自组织特征映射网络(SOFM)之后 ...
- 自组织特征映射(SOFM或SOM)网络解决旅行商问题(TSP)
自组织特征映射(Self-Organizing Feature Map)网络介绍: 由输入层,输出层神经元节点构成的神经网络(由输入层,隐层神经元节点构成的神经网络) 无监督学习 学习准则是胜者为王学 ...
最新文章
- oracle show选项,Oracleshowparameter命令的小技巧有哪些呢?
- 缘何Square可以在移动支付领域上成功?
- python中加入绝对路径_理解Python中的绝对路径和相对路径
- android 多个复选框,Android UI控件之CheckBox(复选框、多选框)
- Linux下C语言使用openssl库进行MD5校验
- hadoop设置java环境_hadoop安装(3)_Linux配置JDK环境
- 3. 什么是icmp?icmp与ip的关系_公共关系与人际交往能力自主模式课程相关
- CentOS7.2 在线安装MySQL8.0
- keras模型训练参数
- Atitit. 构造ast 语法树的总结attilax v2 q0f
- 图扑软件以轻量化建模构建智慧城市
- Cookie、Session 简述
- 理解RoIAlign实际操作
- 坚果pro android版本,坚果Pro有几个版本 哪个版本好?坚果Pro各版本的区别
- APP加密,ios代码混淆工具,虚拟化技术 适用于移动应用程序的虚拟化加密软件
- AutoCAD正版软件多少钱?企业应该采购多少license?
- js模糊匹配(like)
- Dark GDK 初体验
- 线上docker服务频繁自动重启解决过程
- K-Means集群算法
热门文章
- CAN诊断的寻址方式
- Word处理控件Aspose.Words功能演示:使用 Java 比较 MS Word 文档
- 怎样策划微博营销方案
- 抖音四面被拒,再战头条终获offer,系列教学
- IDEA如何导入多个maven项目在pox引入自建包
- M1 docker 安装mysql5.7
- matlab中暂停的快捷键,如何设置“暂停调用”和“强制调用”快捷键
- Slicer学习笔记(二十一)slicer的python接口说明
- (NXP)LS1012 LS1043 LS1046 LS1028 性能PK对比-飞凌嵌入式
- 小电流选线装置的研制之