统计学习方法(二)感知器C语音实现

感知器(perception)是二分类线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1的二值,感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型,感知机学习旨在求出将训练数据进行线性划分的分离超平面,为此导入基于误分类的损失函数,利用梯度下降法对于损失函数进行极小化,求得感知器模型。——–摘自统计学习方法
感知器包含输入层和输出层,主要对线性的数据能有较好的区分效果。
感知器算法总的来说当实例点被误分类,即位于分离的超平面的一侧时,调整w,b的值,使分离超平面向该误分类的一侧移动,以减少该分类点与超平面的距离,直至超平面超过该误分类点使其被正确分类;

感知器分为原始形式和对偶形式,两种形式对感知器求解方法不同。具体对偶形式的感知器可以参考知乎:
https://www.zhihu.com/question/26526858
感知器学习算法原始形式:
输入:训练数据集T={(x1,y1),(x2,y2),⋯,(xn,xn)},其中xi∈χ=Rn,yi∈γ={−1,+1},i=1,2,⋯,N;学习率η(0<η<1);
输出: w,b;感知器模型f(x)=sign(w⋅x+b)
(1) 选取初值w0,b0
(2)在训练集中选取数据(xi,yi)
(3)如果yi(w⋅xi+b)≤0

w←w+ηyixi

b←b+ηyi

(4)转至(2),直到训练集中没有误分类的点
算法实现:
以例2.1为例:

实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
using namespace std;

int w[2] = {0};
int b = 0;
int step = 1;
class point
{
public:
    point();
    void givepoint(int inx,int iny,int intrue);
    ~point();
    int x;
    int y;
    int mytrue;
private:

};

point::point()
{

}
void point::givepoint(int inx,int iny,int intrue)
{
    x = inx;
    y = iny;
    mytrue = intrue;
}

point::~point()
{
}

void minL(point *inpoint,int pointnum)
{
    int tempW[2];
    int tempB=0;
    int tempY;
    int truecount = 0;
    printf("初始w:(%d,%d),b:%d\n", w[0], w[1], b);
    while (1)
    {
        tempW[0] = w[0];
        tempW[1] = w[1];
        tempB = b;
        for (int i = 0; i < pointnum; i++)
        {
            tempY = tempW[0] * inpoint[i].x + tempW[1] * inpoint[i].y + tempB;
            if ((tempY>0 && inpoint[i].mytrue == 1) || (tempY <=0 && inpoint[i].mytrue == -1))
            {
                truecount++;
                continue;
            }
            else
            {
                if (tempY > 0)
                {
                    w[0] = w[0] - step*inpoint[i].x;
                    w[1] = w[1] - step*inpoint[i].y;
                    b = b - step * 1;
                }
                else if (tempY <= 0)
                {
                    w[0] = w[0] + step*inpoint[i].x;
                    w[1] = w[1] + step*inpoint[i].y;
                    b = b + step * 1;
                }
                printf("更新w:(%d,%d),b:%d\n", w[0], w[1], b);
                break;

            }
        }
        if (truecount == 3)
        {
            break;
        }
        else
        {
            truecount = 0;
        }
    }
}
int main()
{
    int pointnum;
    printf("请输入点的个数:\n");
    scanf("%d", &pointnum);
    point *inpoint=new point[pointnum];
    printf("请输入样本点的坐标及样本种类,用正负1表示\n");
    for (int i=0; i < pointnum; i++)
    {
        int tempx, tempy, temptrue;
        scanf("%d%d%d", &tempx, &tempy, &temptrue);
        inpoint[i].givepoint(tempx, tempy, temptrue);
    }
    getchar();
    printf("输入完毕开始分类\n");
    minL(inpoint, pointnum);
    printf("最终w:(%d,%d),b:%d\n", w[0], w[1], b);
    getchar();
}

实现效果:

感知器学习算法对偶形式:
输入:训练数据集T={(x1,y1),(x2,y2),⋯,(xn,xn)},其中xi∈χ=Rn,yi∈γ={−1,+1},i=1,2,⋯,N;学习率η(0<η<1);
输出:a,b;感知机模型f(x)=sign(∑Nj=1ajyjxj⋅x+b)
其中α=(α1,α2,⋯,αN)T
(1)α←0,b←0
(2)在训练集中选取数据(xi,yi)
(3)如果yi{∑Nj=1αjyjxj⋅xi+b}≤0

αi←αi+η

b←b+ηyi

(4)转至(2)直到没有误分类数据
对偶形式中训练实例仅以内积的形式出现,为了方便可以先将训练实例间的内积计算出来并以矩阵的形式储存,用Gram矩阵(还记得现控课上被Gram矩阵笼罩的阴影吗?没错这边又回来了ˋ_ˊ* )

G=[xi⋅xj]N×N

同样用上面的例子实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
using namespace std;

int w[2] = { 0 };
int b = 0;
int step = 1;
int Y[3] = { 0 };
class point
{
public:
    point();
    void givepoint(int inx, int iny, int intrue);
    ~point();
    int x;
    int y;
    int mytrue;
private:

};

point::point()
{

}
void point::givepoint(int inx, int iny, int intrue)
{
    x = inx;
    y = iny;
    mytrue = intrue;
}

point::~point()
{
}

void Duality_minL(point *inpoint, int pointnum,int *alpha,int **gram)
{
    int tempW[2];
    int tempB=0;
    int tempY=0;
    int truecount=0;
    printf("初始a:(%d,%d,%d),b:%d\n", alpha[0], alpha[1], alpha[2], b);
    while (1)
    {
    //  tempW[0] = w[0];
    //  tempW[1] = w[1];
        tempB = b;
        for (int i = 0; i < pointnum; i++)
        {
            tempY = 0;
            for (int j = 0; j <pointnum; j++)
            {
                tempY = tempY + alpha[j] * Y[j] * gram[j][i];
            }
            tempY = tempY + b;
            //Y[i] = tempY;
            if ((tempY>0 && inpoint[i].mytrue == 1) || (tempY <= 0 && inpoint[i].mytrue == -1))
            {
                truecount++;
                continue;
            }
            else
            {
                if (tempY > 0)
                {
                    Y[i] = -1;
                    alpha[i] = alpha[i] + 1;
                    b = b +Y[i]*step;
                }
                else if (tempY <= 0)
                {
                    Y[i] = 1;
                    alpha[i] = alpha[i] + 1;
                    b = b + Y[i] * step;
                }
                printf("更新a:(%d,%d,%d),b:%d\n", alpha[0], alpha[1],alpha[2], b);
                break;
            }

        }
        if (truecount == 3)
        {
            break;
        }
        else
        {
            truecount = 0;
        }
    }
    for (int i = 0; i < pointnum; i++)
    {
        w[0] = w[0] + alpha[i] * inpoint[i].x*inpoint[i].mytrue;
        w[1] = w[1] + alpha[i] * inpoint[i].y*inpoint[i].mytrue;
    }

}
int main()
{
    int pointnum;
    printf("请输入点的个数:\n");
    scanf("%d", &pointnum);
    point *inpoint = new point[pointnum];
    int *alpha = new int[pointnum];
    for (int i = 0; i < pointnum; i++)
    {
        alpha[i] = 0;
    }
    printf("请输入样本点的坐标及样本种类,用正负1表示\n");
    for (int i = 0; i < pointnum; i++)
    {
        int tempx, tempy, temptrue;
        scanf("%d%d%d", &tempx, &tempy, &temptrue);
        inpoint[i].givepoint(tempx, tempy, temptrue);
    }
    int **gram = new int *[pointnum];
    for (int i = 0; i < pointnum; i++)
    {
        gram[i] = new int[pointnum];
    }
    for (int i = 0; i < pointnum; i++)
    {
        for (int j = 0; j < pointnum; j++)
        {
            gram[i][j] = inpoint[i].x*inpoint[j].x + inpoint[i].y*inpoint[j].y;
        }
    }
    getchar();
    printf("输入完毕开始分类\n");
    //minL(inpoint, pointnum);
    Duality_minL(inpoint, pointnum, alpha, gram);
    printf("最终w:(%d,%d),b:%d\n", w[0], w[1], b);
    getchar();
}


这边感知器只能用于对线性的数据集进行二分类,而且因为样本量较少 所以能很快并且无误地将样本的正负集区分开来,当样本量多时可能无法全部无误地区分,这是应该要用到循环次数和损失函数;
暂且先这样,之后再改一下在mnist数据集上进行尝试

时间: 2025-01-21 11:57:18

统计学习方法(二)感知器C语音实现的相关文章

零基础入门深度学习(1):感知器,激活函数

零基础入门深度学习(1) - 感知器零基础入门深度学习(2) - 线性单元和梯度下降零基础入门深度学习(3) - 神经网络和反向传播算法零基础入门深度学习(4) - 卷积神经网络 零基础入门深度学习(5) - 循环神经网络. 零基础入门深度学习(6) - 长短时记忆网络(LSTM). 无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作为一个有理想有追求的程序员,不懂深度学习(Deep Learning)这个超热的技术,会不会感觉马上就out了?现在救

机器学习之感知器

感知器 在讲神经网络前先说说感知器,感知器是一种二分类的线性分类模型,输出值取-1或1.感知器是最基础的神经网络,理解好感知器对后面的各种神经网络模型是很有帮助的.如下图, 它可以有多个输入(x1,x2,...xn),每个输入对应有一个权重(w1,w2...wn),除此之外还有一个偏置项w0. 则输出为 o(x)=⎧⎩⎨⎪⎪1,−1,if∑i=0nxiwi>0;otherwise; 其中将x0看成是1.而 ∑i=0nxiwi=x0w0+x1w1+...+xnwn 则可以看成是x与w的点积. 感知

基础 | 神经网络快速入门:什么是多层感知器和反向传播?

本文对多层感知器和反向传播进行入门级的介绍.作者 Ujjwal Karn 在机器学习领域有三年的从业和研究经验,对深度学习在语音和视觉识别上的应用非常感兴趣. 人工神经网络是一种计算模型,启发自人类大脑处理信息的生物神经网络.人工神经网络在语音识别.计算机视觉和文本处理领域取得了一系列突破,让机器学习研究和产业感到了兴奋.在本篇博文中,我们将试图理解一种称为「多层感知器(Multi Layer Perceptron)」的特定的人工神经网络. 单个神经元 神经网络中计算的基本单元是神经元,一般称作

零基础入门深度学习(1) - 感知器

文章列表 零基础入门深度学习(1) - 感知器 零基础入门深度学习(2) - 线性单元和梯度下降 零基础入门深度学习(3) - 神经网络和反向传播算法 零基础入门深度学习(4) - 卷积神经网络 零基础入门深度学习(5) - 循环神经网络 零基础入门深度学习(6) - 长短时记忆网络(LSTM) 零基础入门深度学习(7) - 递归神经网络 深度学习是啥 在人工智能领域,有一个方法叫机器学习.在机器学习这个方法里,有一类算法叫神经网络.神经网络如下图所示: 上图中每个圆圈都是一个神经元,每条线表示

人工神经网络(Artificial Neural Netwroks)笔记-离散单输出感知器算法

最近在重新学习人工神经网络(Artificial Neural Netwroks),做做笔记,整理思路 离散单输出感知器算法,传说中的MP 二值网络:自变量及其函数的值.向量分量的值只取0和1函数.向量 权向量:W=(w1,w2,w3.....wn) 输入向量:X=(x1,x2,x3.....xn) 训练样本集 {(X,Y)|Y为输入向量X的输出} 训练过程比较简单 如下: 1,初始化权向量W 2,重复下列过程,直到训练完成: 2.1对每个样本(X,Y),重复如下过程: 2.1.1输入X 2.1

人工神经网络(Artificial Neural Netwroks)笔记--离散多输出感知器训练算法

这是对离散单输出感知器算法的扩展 相关的符号定义请参考 <人工神经网络(Artificial Neural Netwroks)笔记-离散单输出感知器算法 > OK,Start Our Game 1.初始化权重矩阵W; 2.重复下列过程,直到训练完成: 2.1对每个样本(X,Y),重复如下过程: 2.1.1 输入X; 2.1.2计算O=F(XW); 2.1.3 for j=1 to m do 执行如下操作: if Oj != Yj then if Oi=0 then for i=1 to n W

人工神经网络(Artificial Neural Netwroks)笔记-连续多输出感知器算法

人工神经网络(Artificial Neural Netwroks)笔记--离散多输出感知器训练算法 中的2.1.3步是多 个判断,因此我们说它是一种离散多输出感知器 现在采用公式 Wij=Wij+α(Yj-Oj)Xi取代了那个步骤 Yj和Oj之间的差别对Wij的影响由α(Yj-Oj)Xi表现出来 这样做的好处是不仅使得算法的控制在结构上更容易理解,而且还使得它的适应面更宽 算法流程如下: 1.用适当的小伪随机数初始化权矩阵W 2.初置精度控制参数ε,学习率α,精度控制变量d=ε+1 3.whi

抽象的艺术 - 感知器

You keep using that word, but I don't think it means what you think it means. 就像上面说的这句话,每当看见"神经网络"这个词的时候,我都是懵逼的,到底啥是神经网络?和深度学习有啥关系?你瞅啥? 懵逼史 作为一个长期进行业务开发的我,在机缘巧合下开始接触算法.刚开始是看各种业务场景如何运用机器学习算法分析和预测的文章,看完之后觉得作者非常牛逼,但是自己是懵逼的.感觉就像耍猴一样,还没学会站着走,就要玩穿火圈了.

统计学习方法笔记 -- 概论

统计学习方法是基于训练数据构建统计模型,从而对数据进行预测和分析.  统计学习分为,监督学习(supervised learning),非监督学习,半监督学习和强化学习(reinforcement learning),其中以监督学习最为常见和重要,所以这里只讨论监督学习 统计学习的过程如下,  1. 获取训练数据集合  2. 确定假设空间,即所有可能的模型的集合  3. 确定模型选择的准则(什么是最优模型的标准),即学习的策略 4. 实现求解最优模型的算法(如何获取最优模型),即学习的算法 5.