感知机
前言
最近学习了c++,俗话说‘光说不练假把式’,所以决定用c++将《统计学习方法》里面的经典模型全部实现一下,代码在这里,请大家多多指教。
感知机虽然简单,但是他可以为学习其他模型提供基础,现在先简单回顾一下基础知识。
感知机模型
上图就是简单的感知机模型,其中fff 我们一般取符号函数
sign(x)={−1,x<0+1,x≥0sign(x)=begin{cases} -1,quad x<0 \\ +1,quad xgeq0 end{cases} sign(x)=⎩⎪⎨⎪⎧−1,x<0+1,x≥0
所以感知机的数学形式就是
y=sign(wx+b)y=sign(wx+b)y=sign(wx+b)
其中w和x都是n维的向量。当n为2时,signsignsign里面的公式有没有特别熟悉?就是直线的公式,n>2就是超平面,用一下课本里面的图就是如下图
这就是分类的根据,必须要注意,感知机只能分离线性可分数据,非线性的不行。
感知机学习策略
提到学习就不得不提到梯度下降算法。感知机的学习策略就是随机梯度下降算法。
具体的在书中讲的很详细,我这里就不赘述了,直接看学习算法吧:
(1) 选取初值w,b。
(2) 选取一组训练数据(x,y)。
(3) 如果y(wx+b)≤0y(wx+b)leq0y(wx+b)≤0,则
w+=lr∗yx w += lr*yxw+=lr∗yx
b+=lr∗yb+=lr*yb+=lr∗y
(4)转至(2)直到没有误分类点。
c++实现感知机
代码结构
实现
首先我有一个基类Base,为了以后的算法继承用的,它包含一个run()的纯虚函数,这样以后就可以在main里面实现多态。
我的数据都存储在私有成员里:
std::vector
std::vector
std::vector
unsigned long indim = 0;
std::vector
std::vector
std::vector
std::vector
std::vector
在main函数里只需要调用每个模型的run()方法,声明的是基类指针:
int main() {
Base* obj = new Perceptron();
obj->run();
delete obj;
return 0;
}
第一步,读取数据并分割。这里用的vector存储。
getData("../data/perceptrondata.txt");
splitData(0.6);//below is split data,and store it intrainData,testData
第二步初始化
std::vector
initialize(init);
第三步进行训练。
在训练时,函数调用顺序如下:
调用computeGradIEnt,进行梯度的计算。对于满足y(wx+b)>0y(wx+b)>0y(wx+b)>0的数据我们把梯度设为0。
std::pair
double lossVal = loss(inputData,groundTruth);
std::vector
double b;
if (lossVal > 0.0)
{
for(auto indata:inputData) {
w.push_back(indata*groundTruth);
}
b = groundTruth;
}
else{
for(auto indata:inputData) {
w.push_back(0.0);
}
b = 0.0;
}
return std::pair
//you also Could return a vector which contains w and b.
}
在调用computeGradIEnt时又调用了loss,即计算−y(wx+b)-y(wx+b)−y(wx+b),loss里调用了inference,用来计算wx+bwx+bwx+b,看起来有点多余对吧,inference函数存在的目的是为了后面预测时候用的。
double Perceptron::loss(const std::vector
double loss = -1.0 * groundTruth * inference(inputData);
std::cout<<"loss is "<< loss < return loss; } double Perceptron::inference(const std::vector //just compute wx+b,for compute loss and predict. if (inputData.size()!=indim){ std::cout<<"input dimension is incorrect. "< throw inputData.size(); } double sum_tem = 0.0; for(int i=0; i sum_tem += inputData[i]*paraData[i]; } sum_tem += paraData[indim]; return sum_tem; } 根据计算的梯度更新w,b voID Perceptron::train(const int & step,const float & lr) { int count = 0; createFeatureGt(); for(int i=0; i if (count==trainDataF.size()-1) count = 0; count++; std::vector double groundTruth = trainDataGT[count]; auto grad = computeGradIEnt(inputData,groundTruth); auto grad_w = grad.first; double grad_b = grad.second; for (int j=0; j paraData[j] += lr * (grad_w[j]); } paraData[indim] += lr * (grad_b); } } 预测用的数据也是之前就分割好的,注意这里的参数始终存在 std::vector 进行预测的代码 int Perceptron::predict(const std::vector double out = inference(inputData); std::cout<<"The right class is "< if(out>=0.0){ std::cout<<"The predict class is 1"< return 1; } else{ std::cout<<"The right class is -1"< return -1; } 以上是内存溢出为你收集整理的统计学习方法c++实现之一 感知机全部内容,希望文章能够帮你解决统计学习方法c++实现之一 感知机所遇到的程序开发问题。 如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)