1.题目

2.解答
#include<iostream>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
typedef vector<double> featureVct;
typedef int label;
class Perceptron;
void printRes(Perceptron pp);
class Perceptron
{
private:
vector<featureVct> FtSet; //特征向量数据集
vector<label> labelSet; //二分类label数据集 +1或-1
double LearnRate; //学习率
featureVct w; //感知机模型参数
double bias; //偏置项
int dimension; //特征向量维度
int count;
public:
Perceptron(int dimension,featureVct w,double bias = 0.0,double learnRate = 1);
int GetCount() const; //获取迭代次数
const featureVct& GetW() const ; //获取模型参数
void SetW(const featureVct& w); //设置模型参数
double GetBias() const; //获取偏置项
void SetBias(double bias); //设置骗置项
bool ReadSource(const string& filePath); //读取数据源
void Train(); //训练模型,得到感知机模型
public:
double VectorDotProduct(const featureVct& f1, const featureVct& f2); //向量点积运算)
featureVct VectorScalarMulti(double num, const featureVct f); //向量数乘运算
featureVct VectorAdd(const featureVct& f1, const featureVct& f2); //向量加法运算
};
const featureVct& Perceptron::GetW() const
{
return w;
}
void Perceptron::SetW(const featureVct& w)
{
this->w = w;
}
double Perceptron::GetBias() const
{
return bias;
}
void Perceptron::SetBias(double bias)
{
this->bias = bias;
}
/*文件格式:每行表示一个样本点,特征值之间用空格隔开,最后一列存储类别信息1或-1*/
bool Perceptron::ReadSource(const string& filePath)
{
ifstream file(filePath);
if (!file)
return false;
while (!file.eof())
{
featureVct dataTmp;
double tmp;
for (int i = 0; i < dimension; ++i)
{
file >> tmp;
dataTmp.push_back(tmp);
}
FtSet.push_back(dataTmp);
label labelData;
file >> labelData;
labelSet.push_back(labelData);
}
return true;
}
void Perceptron::Train()
{
//感知机训练过程
int flag = true;
while (flag)
{
for (int i = 0; i < FtSet.size(); i++)
{
flag = false;
if (labelSet[i] * (VectorDotProduct(w,FtSet[i]) + bias) <= 0)
{
//此处的打印只是为了更直观的给大家展示学习过程,工程中最后不要直接在类中打印信息
printRes(*this);
flag = true;
w = VectorAdd(w, VectorScalarMulti(labelSet[i]*LearnRate,FtSet[i]));
bias += LearnRate * labelSet[i];
++count;
break;
}
}
//此处的打印只是为了更直观的给大家展示学习过程,工程中最后不要直接在类中打印信息
if(!flag) printRes(*this);
}
}
Perceptron::Perceptron(int dimension, featureVct w, double bias, double learnRate)
{
this->dimension = dimension;
this->bias = bias;
this->LearnRate = learnRate;
this->w = w;
count = 0;
}
double Perceptron::VectorDotProduct(const featureVct& f1, const featureVct& f2)
{
double sum = 0.0;
for (int i = 0; i != f1.size(); ++i)
{
sum += f1[i] * f2[i];
}
return sum;
}
featureVct Perceptron::VectorScalarMulti(double num, const featureVct f)
{
featureVct tmp;
for (int i = 0; i != f.size(); ++i)
{
tmp.push_back(num*f[i]);
}
return tmp;
}
featureVct Perceptron::VectorAdd(const featureVct& f1, const featureVct& f2)
{
featureVct tmp(0);
for (int i = 0; i != f1.size(); ++i)
{
tmp.push_back(f1[i] + f2[i]);
}
return tmp;
}
int Perceptron::GetCount() const
{
return count;
}
void printRes(Perceptron pp)
{
cout << "迭代次数:" << pp.GetCount() << endl;
cout << "w:";
featureVct tmp = pp.GetW();
for (int i = 0; i < tmp.size() - 1; ++i)
{
cout << tmp[i] << " ";
}
cout << tmp[tmp.size() - 1] << endl;
cout << "bias:";
cout << pp.GetBias() << endl;
cout << "---------------------------" << endl;
}
int main()
{
featureVct w;
w.push_back(0.0); //设置w初始化参数
w.push_back(0.0);
Perceptron pp(2, w); //创建特征向量为2维的感知机对象
if (!pp.ReadSource("sun.txt"))
{
cout << "读取文件失败";
exit(-1);
}
pp.Train(); //训练得到感知机模型
}数据源:
3 3 1
4 3 1
1 1 -1运行截图:
最后得到 w(1,1) b = -3
大家可能会问,这到底表示什么意思?
其实就是,得到的感知模型表达式为 f(x) = sign(x1+x2-3) 意思也就是我们得到了一条直线x+y-3 = 0 可以作为一个二类划分
注意:感知机器学习算法由于采用不同的初值或选取不同的误分类点,解可以不同
此题的详细解法描述参照《统计学习方法》赵航P45
版权声明:本文为tiankong_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。