如何用C语言做KNN
使用C语言实现KNN算法包括以下几个关键步骤:数据预处理、计算距离、选择最近邻、进行分类。 其中,计算距离是KNN算法的核心部分,常用的距离度量方法包括欧氏距离、曼哈顿距离等。
KNN(K-Nearest Neighbors)是一种基于实例的学习算法,广泛应用于分类和回归任务中。KNN算法的核心思想是,通过计算待分类样本与训练样本集中的所有样本之间的距离,找到距离最近的K个样本(即K个最近邻),然后根据这些最近邻的类别信息确定待分类样本的类别。以下是如何用C语言实现KNN算法的详细步骤:
一、数据预处理
在任何机器学习算法中,数据预处理都是至关重要的一步。在KNN算法中,我们需要将数据集分为训练集和测试集,并确保数据的质量。
1. 数据读取
首先,我们需要从文件或其他数据源中读取数据。在C语言中,可以使用标准输入输出库函数来读取数据,例如fscanf
函数。
#include <stdio.h>
void readData(const char *fileName, double data[][4], int *numSamples) {
FILE *file = fopen(fileName, "r");
if (file == NULL) {
printf("Unable to open file %sn", fileName);
return;
}
int i = 0;
while (fscanf(file, "%lf,%lf,%lf,%lf", &data[i][0], &data[i][1], &data[i][2], &data[i][3]) != EOF) {
i++;
}
*numSamples = i;
fclose(file);
}
2. 数据标准化
为了避免特征值的尺度差异对距离计算的影响,我们通常需要对数据进行标准化处理。常用的方法包括归一化和Z-score标准化。
void normalizeData(double data[][4], int numSamples) {
for (int j = 0; j < 4; j++) {
double minVal = data[0][j], maxVal = data[0][j];
for (int i = 1; i < numSamples; i++) {
if (data[i][j] < minVal) minVal = data[i][j];
if (data[i][j] > maxVal) maxVal = data[i][j];
}
for (int i = 0; i < numSamples; i++) {
data[i][j] = (data[i][j] - minVal) / (maxVal - minVal);
}
}
}
二、计算距离
计算距离是KNN算法的核心部分,常用的距离度量方法包括欧氏距离和曼哈顿距离。
1. 欧氏距离
欧氏距离是最常用的距离度量方法,计算公式为:
[ d(x, y) = sqrt{sum_{i=1}^{n} (x_i – y_i)^2} ]
#include <math.h>
double euclideanDistance(double *vec1, double *vec2, int length) {
double sum = 0.0;
for (int i = 0; i < length; i++) {
sum += (vec1[i] - vec2[i]) * (vec1[i] - vec2[i]);
}
return sqrt(sum);
}
2. 曼哈顿距离
曼哈顿距离的计算公式为:
[ d(x, y) = sum_{i=1}^{n} |x_i – y_i| ]
double manhattanDistance(double *vec1, double *vec2, int length) {
double sum = 0.0;
for (int i = 0; i < length; i++) {
sum += fabs(vec1[i] - vec2[i]);
}
return sum;
}
三、选择最近邻
在计算完测试样本与所有训练样本之间的距离后,我们需要选择距离最近的K个样本。
typedef struct {
double distance;
int index;
} Neighbor;
int compareNeighbors(const void *a, const void *b) {
Neighbor *neighborA = (Neighbor *)a;
Neighbor *neighborB = (Neighbor *)b;
return (neighborA->distance > neighborB->distance) - (neighborA->distance < neighborB->distance);
}
void findKNearestNeighbors(double data[][4], double *testSample, int numSamples, int k, Neighbor *neighbors) {
for (int i = 0; i < numSamples; i++) {
neighbors[i].distance = euclideanDistance(data[i], testSample, 4);
neighbors[i].index = i;
}
qsort(neighbors, numSamples, sizeof(Neighbor), compareNeighbors);
}
四、进行分类
最后一步是根据最近邻的类别信息进行分类。对于分类任务,可以使用多数投票的方法,即选取K个最近邻中出现次数最多的类别作为测试样本的类别。
int classify(double data[][4], int *labels, double *testSample, int numSamples, int k) {
Neighbor neighbors[numSamples];
findKNearestNeighbors(data, testSample, numSamples, k, neighbors);
int count[3] = {0, 0, 0}; // 假设有3个类别
for (int i = 0; i < k; i++) {
int label = labels[neighbors[i].index];
count[label]++;
}
int maxCount = 0, classification = -1;
for (int i = 0; i < 3; i++) {
if (count[i] > maxCount) {
maxCount = count[i];
classification = i;
}
}
return classification;
}
五、示例代码
以下是一个完整的示例代码,展示了如何使用C语言实现KNN算法:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct {
double distance;
int index;
} Neighbor;
void readData(const char *fileName, double data[][4], int *numSamples);
void normalizeData(double data[][4], int numSamples);
double euclideanDistance(double *vec1, double *vec2, int length);
int compareNeighbors(const void *a, const void *b);
void findKNearestNeighbors(double data[][4], double *testSample, int numSamples, int k, Neighbor *neighbors);
int classify(double data[][4], int *labels, double *testSample, int numSamples, int k);
int main() {
const char *fileName = "data.txt";
double data[100][4];
int labels[100];
int numSamples;
readData(fileName, data, &numSamples);
normalizeData(data, numSamples);
double testSample[4] = {5.1, 3.5, 1.4, 0.2};
int k = 3;
int result = classify(data, labels, testSample, numSamples, k);
printf("The predicted class is: %dn", result);
return 0;
}
void readData(const char *fileName, double data[][4], int *numSamples) {
FILE *file = fopen(fileName, "r");
if (file == NULL) {
printf("Unable to open file %sn", fileName);
return;
}
int i = 0;
while (fscanf(file, "%lf,%lf,%lf,%lf", &data[i][0], &data[i][1], &data[i][2], &data[i][3]) != EOF) {
i++;
}
*numSamples = i;
fclose(file);
}
void normalizeData(double data[][4], int numSamples) {
for (int j = 0; j < 4; j++) {
double minVal = data[0][j], maxVal = data[0][j];
for (int i = 1; i < numSamples; i++) {
if (data[i][j] < minVal) minVal = data[i][j];
if (data[i][j] > maxVal) maxVal = data[i][j];
}
for (int i = 0; i < numSamples; i++) {
data[i][j] = (data[i][j] - minVal) / (maxVal - minVal);
}
}
}
double euclideanDistance(double *vec1, double *vec2, int length) {
double sum = 0.0;
for (int i = 0; i < length; i++) {
sum += (vec1[i] - vec2[i]) * (vec1[i] - vec2[i]);
}
return sqrt(sum);
}
int compareNeighbors(const void *a, const void *b) {
Neighbor *neighborA = (Neighbor *)a;
Neighbor *neighborB = (Neighbor *)b;
return (neighborA->distance > neighborB->distance) - (neighborA->distance < neighborB->distance);
}
void findKNearestNeighbors(double data[][4], double *testSample, int numSamples, int k, Neighbor *neighbors) {
for (int i = 0; i < numSamples; i++) {
neighbors[i].distance = euclideanDistance(data[i], testSample, 4);
neighbors[i].index = i;
}
qsort(neighbors, numSamples, sizeof(Neighbor), compareNeighbors);
}
int classify(double data[][4], int *labels, double *testSample, int numSamples, int k) {
Neighbor neighbors[numSamples];
findKNearestNeighbors(data, testSample, numSamples, k, neighbors);
int count[3] = {0, 0, 0}; // 假设有3个类别
for (int i = 0; i < k; i++) {
int label = labels[neighbors[i].index];
count[label]++;
}
int maxCount = 0, classification = -1;
for (int i = 0; i < 3; i++) {
if (count[i] > maxCount) {
maxCount = count[i];
classification = i;
}
}
return classification;
}
这个示例代码展示了如何使用C语言实现KNN算法的基本步骤。通过这些步骤,可以有效地进行分类任务。当然,在实际应用中,可能需要进行更多的优化和调整,以适应不同的数据和需求。
相关问答FAQs:
Q: 什么是KNN算法?
A: KNN算法是一种机器学习算法,全称为K-最近邻算法。它通过计算待分类样本与训练集中最近的K个样本的距离来进行分类。KNN算法基于样本的相似性,将待分类样本归类到与其最相似的样本所属的类别。
Q: 在C语言中如何实现KNN算法?
A: 在C语言中,实现KNN算法需要以下步骤:
- 读取训练集和待分类样本的数据。
- 计算待分类样本与训练集中每个样本的距离。
- 根据距离找出K个最近的样本。
- 统计K个最近样本中各类别的数量。
- 将待分类样本归为数量最多的类别。
Q: 如何计算两个样本之间的距离?
A: 在KNN算法中,常用的计算样本之间距离的方法有欧氏距离和曼哈顿距离。欧氏距离是通过计算两个样本在各个特征维度上的差值的平方和再开方得到的。曼哈顿距离是通过计算两个样本在各个特征维度上的差值的绝对值之和得到的。在C语言中,可以使用相关的数学函数来实现这些计算。
原创文章,作者:Edit1,如若转载,请注明出处:https://docs.pingcode.com/baike/989521