#ifndef _ADA_BOOST_
#define _ADA_BOOST_
#include<iostream>
#include<vector>
#include<math.h>
#include<unordered_map>
#include<algorithm>
using namespace std;
class adaBoost
{
public:
adaBoost(unordered_map<double, int>trainData1, double alpha1, int iterNums1,int classifyNums1,vector<double> data1);
void weekClassify(double alpha, int iterNums,vector<vector<double>> weight,int nums);
void adaptWeight(int num);
void adaptGmWeight(int num);
double findMin(const vector<double>& data);
void getResult();
private:
vector<double> data; //样本值
unordered_map<double, int> trainData; //快速提供类型的作用
vector<vector<double>> weight; //训练数据权值 迭代一次更新一次
int iterNums; //迭代次数
int classifyNums; //分类器个数
vector<double> error; //记录错误率
double alpha; //迭代步长
vector<double> gmWeight; //记录弱分类器权值
vector<double> gm; //记录弱分类器
vector<int> gmSymbol; //对应分类器符号
vector<vector<int>> errorPos; //记录错误点位置
};
#endif // !_ADA_BOOST_
#include"AdaBoost.h"
adaBoost::adaBoost(unordered_map<double, int> trainData1, double alpha1, int iterNums1, int classifyNums1, vector<double> data1) /*:
trainData(trainData1), alpha(alpha1), iterNums(iterNums1), classifyNums(classifyNums1), data(data1)*/ {
trainData = trainData1;
alpha = alpha1;
iterNums = iterNums1;
data = data1;
classifyNums = classifyNums1;
int nums = trainData.size();
vector<double> vec; //第一次迭代权值初始化
for (int i = 0; i < nums; i++) {
vec.push_back(1.0 / nums);
}
weight.push_back(vec); //1/n
for (int i = 0; i < classifyNums; i++) {
weekClassify(alpha, iterNums, weight, i); //弱分类器 迭代次数 步长 本次迭代的权值(classifyNums确定)
adaptGmWeight(i); //更新分类器权值
adaptWeight(i); //更新权重
}
}
double adaBoost::findMin(const vector<double>& data) {
double min = data[0];
for (int i = 1; i < data.size(); i++) {
if (data[i] <= min)
min = data[i];
else
;
}
return min;
}
//void adaBoost::weekClassify(unordered_map<double, int>&trainData, double alpha, int iterNums, vector<vector<double>> weight, int nums) {
// int nums = iterNums; //迭代算出本次权重下的最小错误率
// double begin = findMin(data);
// double error1=-1;
// double classify = 0;
// vector<double> vec = weight[ nums-classifyNums];
// for (int i = 0; i < iterNums; i++) {
// double errNums = 0; //先左-1 再左 1 判断
// double errNums1 = 0;
// double errNums2 = 0;
// begin = alpha*i + begin;
// for (int j = 0; j < data.size(); j++) {
// if (data[j] <= begin&&trainData[data[j]] == 1) { //错误项乘权重 不是记录错误次数
// errNums=errNums*vec[j];
// }
// else if (data[j] > begin&&trainData[data[j]] == -1) {
// errNums = errNums*vec[j];
// }
// else if (data[j] <= begin&&trainData[data[j]] == -1)
// errNums1 = errNums1*vec[j];
// else if (data[j] > begin&&trainData[data[j]] == 1)
// errNums1 = errNums1*vec[j];
// }
//
// if (errNums1 > errNums)
// errNums2 = errNums;
// else
// errNums2 = errNums1;
//
// if (error1 == -1)
// error1 = errNums2;
// else {
// if (errNums2 > error1)
// ;
// else {
// error1 = errNums2;
// classify = begin;
// }
// }
// }
// gm.push_back(classify);
// error.push_back(error1);
//}
void adaBoost::weekClassify(double alpha, int iterNums, vector<vector<double>> weight, int nums) {
double begin = findMin(data); //大循环结束 记录一个分类器(数值 符号)
double errorNums3 = -1;
int symbol1 = 0;
double gmValue = 0;
vector<int> vec3; //记录错误点位置
for (int i = 0; i < iterNums; i++) {
begin = begin + i*alpha;
double errorNums = 0;
double errorNums1 = 0;
double errorNums2 = 0;
int symbol = 0;
vector<int> vec1; //记录错误点1
vector<int> vec2; //记录错误点2
for (int j = 0; j < data.size(); j++) { //比较 对比 错误率 记录最优
if (data[j] <= begin&&trainData[data[j]] == 1) { //小的默认-1 大的默认1 这表示分类错了 记录下来
errorNums = errorNums + weight[nums][j];
vec1.push_back(j);
}
if (data[j] > begin&&trainData[data[j]] == -1) {
errorNums = errorNums + weight[nums][j];
vec1.push_back(j);
}
if (data[j] <= begin&&trainData[data[j]] == -1) {
errorNums1 = errorNums1 + weight[nums][j];
vec2.push_back(j);
}
if (data[j] > begin&&trainData[data[j]] == 1) {
errorNums1 = errorNums1 + weight[nums][j];
vec2.push_back(j);
}
}
if (errorNums <= errorNums1) { //同一小循环若分类器 不知道 -1 +1 谁小保留谁 再与大循环比较 谁小 保留谁 得到最终弱分类器
errorNums2 = errorNums;
symbol = -1;
}
else {
errorNums2 = errorNums1;
symbol = 1;
}
if (errorNums3 == -1) {
errorNums3 = errorNums2;
symbol1 = symbol;
gmValue = begin;
if (symbol1 == -1)
vec3 = vec1;
else
vec3 = vec2;
}
else {
if (errorNums3 <= errorNums2)
;
else {
errorNums3 = errorNums2;
symbol1 = symbol;
gmValue = begin;
if (symbol1 == -1)
vec3 = vec1;
else
vec3 = vec2;
}
}
}
gm.push_back(gmValue); //最终记录数据 分类器值 方向 错误率
gmSymbol.push_back(symbol1);
error.push_back(errorNums3);
errorPos.push_back(vec3);
}
void adaBoost::adaptGmWeight(int num) {
double em = (1 - error[num]) / error[num];
gmWeight.push_back((1.0 / 2)*log(exp(em)));
}
void adaBoost::adaptWeight(int num) {
vector<double> nextWeight;
for (int i = 0; i < data.size(); i++) { //大循环 求出每一个样本的更新权值
int Yi = trainData[data[i]];
int GmXi1=Yi;
double Wnext;
double Zm = 0;
for (int j = 0; j < data.size(); j++) { //二循环求出 zm归一化值
int yi = trainData[data[j]];
double GmXi=yi;
for (int p = 0; p < errorPos[num].size(); p++) {
if (errorPos[num][p] == j)
GmXi = -yi;
}
Zm = Zm + weight[num][j] * exp(-gmWeight[num] * yi*GmXi);
}
for (int k = 0; k < errorPos[num].size(); k++) {
if (errorPos[num][k] == i)
GmXi1 = -Yi;
}
Wnext = (weight[num][i] / Zm)*exp(-gmWeight[num] * Yi*GmXi1);
nextWeight.push_back(Wnext);
}
weight.push_back(nextWeight);
}
void adaBoost::getResult() {
for (auto c : gm)
cout << "弱分类器值" << c<<" ";
for (auto c : gmWeight)
cout << "弱分类器权值" <<c<< " ";
for (auto c : gmSymbol)
cout << "弱分类器方向" << c<<" ";
}