relief算法是一种常用的特征选择方法,用于从原始数据集中选择出最具代表性的特征集合。其基本思想是通过计算特征与类别之间的相关性,来评估每个特征的重要性,然后选择出权重最高的一组特征作为最终的特征集合。
relief算法的基本步骤如下:
1. 初始化权重向量w为0;
2. 随机选择一个样本x;
3. 找到与x最近的同类样本和异类样本,分别记为near_hit和near_miss;
4. 更新权重向量w,对于每一个特征i,有:
- 如果x的特征i与near_hit的特征i相同,w[i] = w[i] + 1;
- 如果x的特征i与near_miss的特征i相同,w[i] = w[i] - 1;
5. 重复步骤2-4,直到所有样本都被处理过;
6. 根据权重向量w的大小,选择权重最高的k个特征作为最终的特征集合。
下面是C++实现的relief算法代码:
```c++
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// 计算两个样本之间的距离
double distance(vector<double>& x, vector<double>& y) {
double d = 0.0;
for (int i = 0; i < x.size(); ++i) {
d += pow(x[i] - y[i], 2);
}
return sqrt(d);
}
// 计算relief算法中的权重向量
vector<double> relief(vector<vector<double>>& data, vector<int>& labels, int k) {
// 初始化权重向量w为0
vector<double> w(data[0].size(), 0.0);
// 遍历每一个样本
for (int i = 0; i < data.size(); ++i) {
vector<double>& x = data[i];
int label = labels[i];
// 找到与x最近的k个样本
vector<pair<double, int>> distances;
for (int j = 0; j < data.size(); ++j) {
if (i == j) continue;
double d = distance(x, data[j]);
distances.push_back(make_pair(d, j));
}
sort(distances.begin(), distances.end());
// 找到与x最近的同类样本和异类样本
int near_hit = -1, near_miss = -1;
for (int j = 0; j < distances.size(); ++j) {
int idx = distances[j].second;
if (labels[idx] == label) {
near_hit = idx;
break;
}
}
for (int j = distances.size() - 1; j >= 0; --j) {
int idx = distances[j].second;
if (labels[idx] != label) {
near_miss = idx;
break;
}
}
// 更新权重向量w
if (near_hit != -1) {
for (int j = 0; j < x.size(); ++j) {
if (x[j] == data[near_hit][j]) {
w[j] += 1.0;
}
}
}
if (near_miss != -1) {
for (int j = 0; j < x.size(); ++j) {
if (x[j] == data[near_miss][j]) {
w[j] -= 1.0;
}
}
}
}
// 根据权重向量w的大小,选择权重最高的k个特征作为最终的特征集合
vector<pair<double, int>> sorted_w;
for (int i = 0; i < w.size(); ++i) {
sorted_w.push_back(make_pair(w[i], i));
}
sort(sorted_w.begin(), sorted_w.end(), greater<pair<double, int>>());
vector<double> result(k, 0.0);
for (int i = 0; i < k; ++i) {
result[i] = sorted_w[i].second;
}
return result;
}
int main() {
// 测试数据集
vector<vector<double>> data = {
{1.1, 2.2, 3.3},
{2.2, 3.3, 4.4},
{3.3, 4.4, 5.5},
{4.4, 5.5, 6.6},
{5.5, 6.6, 7.7},
{6.6, 7.7, 8.8},
{7.7, 8.8, 9.9},
{8.8, 9.9, 10.0},
{9.9, 10.0, 11.1},
{10.0, 11.1, 12.2}
};
vector<int> labels = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
// 使用relief算法选择2个最重要的特征
vector<double> features = relief(data, labels, 2);
// 输出选择出的特征
for (int i = 0; i < features.size(); ++i) {
cout << features[i] << " ";
}
cout << endl;
return 0;
}
```