KNN分类与案例实战

本文主要对KNN的分类算法进行验证,以及如何编写KNN,以及KNN的应用。
KNN主要运用于数据分类,本文通过某电站的仿真数据进行验证分析。
官方KNN的调用:

from sklearn.neighbors import KNeighborsClassifier

# 3表示最近的3个点作为分类标准
knn = KNeighborsClassifier(3)
# x表示训练数据, y表示训练数据标签
knn.fit(x, y)
# X表示测试数据
result = knn.predict(X)

官方KNN验证,本文通过电厂仿真数据验证。数据分别是100%、90%、80%工况下的平稳数据。

# 制作数据
data1 = pd.read_excel("100.xlsx")
data2 = pd.read_excel("90.xlsx")
data3 = pd.read_excel("80.xlsx")

d1 = np.array(data1.values)[:, 1:]
d2 = np.array(data2.values)[:, 1:]
d3 = np.array(data3.values)[:, 1:]

# 取前100个数据作为训练数据
x = list(d1[:100, :])
x.extend(list(d2[:100, :]))
x.extend(list(d3[:100, :]))

# 制作数据标签
y = []
for i in range(100):
    y.append(1)
for i in range(100):
    y.append(2)
for i in range(100):
    y.append(3)

结果:

# 取100%工况下100后的所有数据测试
result = knn.predict(d1[100:, :])

# 取90%工况下100后的所有数据测试
result = knn.predict(d2[100:, :])

在这里插入图片描述

# 取80%工况下100后的所有数据测试
result = knn.predict(d3[100:, :])

在这里插入图片描述
KNN自己编写:

class KNeighborsClassifier:
    def __init__(self, k, d="e", p=3):
        """
        :param k: 样本的前几个最近点
        :param d: 距离的计算方式,"e" 欧式距离 "ma"曼哈顿距离 "c"切比雪夫距离 "mi"闵氏距离
        :param p: "mi"距离下p的值
        """
        self.k = k
        self.d = d
        self.p = p

    def EuchdeanDistance(self, sub_X, sub_x):
        # 欧氏距离
        return np.sqrt(np.dot(sub_x - sub_X, sub_x - sub_X))

    def ManhattanDistance(self, sub_X, sub_x):
        # 曼哈顿距离
        return np.sum(np.abs(sub_X - sub_x))

    def ChebyshevDistance(self, sub_X, sub_x):
        # 切比雪夫距离
        return max(np.abs(sub_x - sub_X))

    def MinkowskiDistance(self, sub_X, sub_x, p):
        # 闵氏距离
        return np.power(np.sum(np.power(sub_x - sub_X, p)), 1/p)

    def fit(self, x, y):
        """
        :param x: 训练样本
        :param y: 训练样本标签
        :return: 无返回值
        """
        # 检查数据格式是否正确
        self.x = np.array(x)
        self.y = np.array(y)
        if self.x.shape[0] != self.y.shape[0]:
            raise ValueError("x 与 y维度不同!需要相同的维度")
        if self.x.ndim != 2:
            raise ValueError("x必须是一个二维数组")

    def predict(self, X):
        """
        :param X: 测试样本
        :return result: 预测的测试样本标签
        """
        self.X = np.array(X)
        # 判断测试样本X与训练样本x的维度是否相同
        if self.X.shape[1] != self.x.shape[1]:
            ValueError("x与X维度不同!需要相同的维度")
        # 记录X中每一个样本所对应的标签
        result = []
        # 记录最小距离
        mini_dis = []
        # 计算X中每个样本与x中所有样本的距离
        for i in self.X:
            # 记录每一个X样本对应所有x样本的距离
            distance = []
            # 记录前self.k个距离最小样本对应的标签
            index = []
            for j in self.x:
                if self.d == "e":
                    distance.append(self.EuchdeanDistance(i, j))
                if self.d == "ma":
                    distance.append(self.ManhattanDistance(i, j))
                if self.d == "c":
                    distance.append(self.ChebyshevDistance(i, j))
                if self.d == "mi":
                    distance.append(self.MinkowskiDistance(i, j, self.p))
            # 将距离进行排序返回对应的索引,并选取前k个最短距离
            sort = np.argsort(distance)[:self.k]
            mini_dis.append(distance[sort[0]])
            for j in sort:
                index.append(self.y[j])
            # 计算重复元素的个数
            counter = Counter(index)
            # 查找最大元素对应的标签
            label = max(counter)
            result.append(label)
        return result, mini_dis

自己编写程序验证:

# 100%工况,曼哈顿距离下验证
knn = KNeighborsClassifier(3,d="ma")
knn.fit(x, y)
# 只取分类结果,_表示舍弃
result, _ = knn.predict(d1[100:, :])

在这里插入图片描述

# 90%工况,曼哈顿距离下验证
knn = KNeighborsClassifier(3,d="ma")
knn.fit(x, y)
# 只取分类结果,_表示舍弃
result, _ = knn.predict(d2[100:, :])

在这里插入图片描述

# 80%工况,曼哈顿距离下验证
knn = KNeighborsClassifier(3,d="ma")
knn.fit(x, y)
# 只取分类结果,_表示舍弃
result, _ = knn.predict(d3[100:, :])

在这里插入图片描述
从上面可以看出自己编写的KNN可以进行正确的分类。(但运行速度可能较慢,由于官方KNN由kd树,并行加速等,等学会再更)。

KNN进行异常或故障数据判断,KNN不仅可以用来分类,还能进行异常或故障数据判断,通过测试数据每个数据点与训练数据所有样本最小距离来判断,正常情况下的数据点最小距离较小,当发生异常时异常样本与正常样本距离会变大,可以通过此方法来判断异常数据。

验证:

    data1 = pd.read_excel("100.xlsx")
    data4 = pd.read_excel("100%工况下故障数据.xlsx")

    d1 = np.array(data1.values)[:, 1:]
    d4 = np.array(data4.values)[:, 1:]

    x = list(d1[:100, :])
    
    y = []
    for i in range(100):
        y.append(1)

    knn = KNeighborsClassifier(3, d="e")
    knn.fit(x, y)
    _, mini_dis = knn.predict(d4)
    print(mini_dis)
    plt.plot(mini_dis)
    plt.xlabel("时间(s)")
    plt.ylabel("距离")
    plt.show()

数据在400s左右发生异常。
在这里插入图片描述

由上图可见正常数据与异常数据可以通过距离来进行区别。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值