[C++ & AdaBoost] 傻陈带你用C++实现AdaBoost

前言

人工智能的算法需要许多预备知识,但时间比较紧,所以我只会对"对最后算法实现有帮助的资料"感兴趣,试着在不完全了解的情况下将这次实验完成。

数据集

这次要学习的数据集是UCI上的Polish companies bankruptcy data Data Set
数据集就是一堆数据的集合,而这次实验就是要对这个“破产公司”数据集进行分类。
这个数据集包含了5个.arff格式的文件,分别对应五年的数据。
我借鉴《Matlab读取.arff文件》的教程,用Excel查看了里面的内容,一个文件大概有七千条公司的记录,每条记录都有65个属性。其中前64个属性是实数格式,个别可能出现’?’,应该是‘不清楚’的意思;最后一个属性是0或1,代表了这条记录的类别(我猜测是破产/不破产)。
我要做的就是,用这些记录的属性和类别去给算法学习,达到能只凭属性来预测类别的程度。

AdaBoost

机器学习实战教程(十):提升分类器性能利器-AdaBoost
网上有大把的参考资料还算庆幸,这里举了个例子。当然要短时间完全理解还是天方夜谭的。

思路

AdaBoost大致是靠调整弱分类器的权重来运作的。
弱分类器可以暂时理解为对某个属性设置一个阈值,如果达到阈值就直接归为类1,未达到就归为类0。
一开始Adaboost导入作为训练数据的记录,根据一个弱分类器来分类所有的记录。然后对比判断结果与每条记录的实际类别的差距,来纠正这个弱分类器的权重和各个记录的权重,最后就智能的学习出了由多个带权重的弱分类器合并的强分类器,同时也可以通过记录的权重来排除不必要的训练记录。

设计

  • 训练模式
    • 导入训练数据
    • 对训练数据定权重D={k,k,k,…,k,k},暂时先不知道k为多少合适,总之全员相等。
    • 加载训练数据,使用弱分类器来预测分类,最后选定误差最小的一个弱分类器开始训练
    • 给分错的数据和分对的数据分别调整数据的权重
    • 对比预测和实际,然后通过某种方式来设定分类器权重α。
    • 将带权重的弱分类器加入到强分类器中,得出强分类器的当前指标。
    • 循环迭代进行下一次训练。

难点

1.如何将.arff里的内容输入到C++程序呢?
2.k应该是多少呢?
3.如何建立初始的弱分类器
4.某种方式是什么呢?
这些纯属代码之外的知识盲区,还是优先解决的好。

Solve 1

在前面我已经成功的用Excel查看了里面的内容,如果用记事本打开的话,数据部分其实就是用逗号分隔的记录们。
.arff文件是无法识别的,但我可以单纯的将数据部分作为新的输入文件,然后以逗号分割整个文件,得到的集合就都是数字为元素的,再以每65个为一条记录即可。

Solve 2

初始权重在AdaBoost的教程中其实已经规定,为w=1/N,作为第一次迭代时各个记录的权重。可以说非常标准了。

Solve 3

虽然AdaBoost有加强分类器的能力,但是尽量还是让弱分类器本身的误差率最小比较好。所以在AdaBoost之前,弱分类器也是要训练出来的。
因为弱分类器本身是很简单的,类似
H 1 = { 1 , X 35 > 9.8 − 1 , X 35 ≤ 9.8 H_{1}=\left\{\begin{matrix} 1,X_{35}>9.8\\ -1,X_{35}\leq 9.8 \end{matrix}\right. H1={ 1,X35>9.81,X359.8表示若记录的第35个属性>9.8,那么就取1,反之就取-1。
分类预测时,就看分类器的结果是正还是负,正为类1,负为类0。
所以误差率就是分错的记录占总记录数的比例。
因此很容易想到,只要在某个属性的数据范围内,遍历各种可能的阈值和方向(大还是小),取其中误差最小的即可。
例如:数据分布在-10~90之间,我可以以10为步长遍历,也就是从-10,0, … ,80,90中挑出一个分类结果最准确的阈值即可。

Solve 4

Solve 4是Adaboost的核心计算部分,先要从原理上了解才能写出相应的代码。
Adaboost算法原理分析和实例+代码(简明易懂)
1.选取一个误差率最小的弱分类器H,对所有数据分类,计算当前弱分类器的误差度。
误差度ε等于分错的样本的权值之和。
2.计算该弱分类器的权重
α = 1 2 l n ( 1 − ε ε ) \alpha=\frac{1}{2}ln(\frac{1-\varepsilon }{\varepsilon }) α=21ln(ε1ε)
3.计算分对记录和分错记录的权重
当记录被分对时,该记录新权重为:
D n e w = D o l d 2 ( 1 − ε ) D_{new}=\frac{D_{old}}{2(1-\varepsilon )} Dnew=2(1ε)Dold
当记录被分错时,该记录新权重为:
D n e w = D o l d 2 ε D_{new}=\frac{D_{old}}{2\varepsilon } Dnew=2εDold

编程

因为想以实现预期效果为目标,所以运行效率和最终结果会有点不尽人意。

输入输出环境配置

数据集是以文件的形式存在的,想到输入输出都走文件渠道

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;

#define LOCAL

int main()
{
   
#ifdef LOCAL  
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif  
	return 0;
}

代码说明
1.若Visual Studio出现报错"freopen:This function…",那么就在解决方案资源管理器里,右键项目名>属性>C/C++>常规>SDL检查>“是"改成"否”。
2.这段代码会使程序以input.txt作为标准输入流,然后输出会在output.txt中显示

输入数据集

//训练集记录的结构体
struct Record
{
   
	bool hasValue[64];//64个属性是否存在
	double attr[64];//64个属性的值
	double weight;//记录的权重
	int type;//类别,0或1
};

vector<Record> recs;//训练集

//功能:遍历字符串str,将里面的','替换为空格
void replaceComma(string& str)
{
   
	for (int i = 0; i < str.length(); i++)
	{
   
		if (str[i] == ',') 
			str[i] = ' ';
	}
}

//功能:输入训练集文件,将训练集的数据保存在recs之中
void inputRecords()
{
   
	Record tempRec;
	string line;
	while (!cin.eof())
	{
   
		//一行作为一条完整记录
		getline(cin, line);
		if (line == "") break;
		replaceComma(line);

		stringstream ss(line);//一行的字符串作为输入流
		for (int i = 0; i < 64; i++)
		{
   
			//排除值为'?'的属性
			string tempStr;
			ss >> tempStr;
			if (tempStr != "?")
			{
   
				tempRec.hasValue[i] = true;
				//把string类型转化为double类型
				stringstream tempSS(tempStr);
				tempSS >> tempRec.attr[i];
			}
			else
				tempRec.hasValue[i] = false;
		}
		ss >> tempRec.type;//记录的最后一个数字代表类别

		//记录+1
		recs.push_back(tempRec);
	}
	//给所有记录赋初始权重
	double numOfRecords = recs.size();
	for (vector<Record>::iterator it = recs.begin(); it 
  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Haar分类器是一种基于Haar特征的目标检测方法。它是通过训练一个级联分类器来进行目标的识别和分类。以下是实现Haar分类器的一般步骤: 1. 数据收集:首先需要收集包含正样本和负样本的训练数据集。正样本是含有目标的图像,负样本是不含目标的图像。 2. 特征提取:通过Haar特征提取方法,从正样本和负样本中提取特征。Haar特征是基于图像局部区域的像素差值计算得出的。 3. 特征选择:从提取的Haar特征中选择一部分较为区分目标和非目标的特征。这一步通常使用Adaboost算法来进行特征选择,通过训练多个弱分类器。 4. 弱分类器训练:通过训练多个基于选择的特征的弱分类器,每个弱分类器根据特征的权重对图像进行分类。 5. 级联分类器构建:将多个弱分类器连接起来形成一个级联分类器。级联分类器的结构是由多个弱分类器按顺序排列组成,每个弱分类器的输出都通过下一个弱分类器进行检验。 6. 级联分类器训练:通过训练级联分类器,迭代地对图像进行识别和分类,直到达到所需的准确率。 7. 检测:将训练好的级联分类器应用于待检测的图像,对图像进行目标检测和分类。 总的来说,Haar分类器的实现主要包括数据收集、特征提取、特征选择、弱分类器训练、级联分类器构建、级联分类器训练和目标检测等步骤。这些步骤的顺序和具体实现方式可能会根据具体情况有所不同,但是核心思想和方法是类似的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值