机器学习-------KNN分类算法实现玻璃分类

机器学习-------KNN分类算法实现玻璃分类

本博客的实验数据是从uci数据集官网上下载下来的(链接: http://archive.ics.uci.edu/ml/datasets/Glass+Identification.)。
(最近在学机器学习,发现机器学习挺有意思的,就大体记录一下。)
首先,机器学习中数据处理占有十分重要的地位。Glass 数据集一共有214条记录,每条记录有10个特征,分别为:Id,RI,Na,Mg,Al,Si,K,Ca,Ba,Fe。 根据这10个特征属性,最终将玻璃划分为building_windows_float_processed,building_windows_non_float_processed,vehicle_windows_float_processed,vehicle_windows_non_float_processed,containers,tableware,headlamps,共7类,其中第4类无数据。
这里对数据的处理很简单,因为下载下来的这个Glass数据集没有缺失,并且都是数值。所以只去除了不需要的Id列,并进行去重处理,得到213条数据。 然后拆分数据集,按照7:3的比例将其随机拆分成训练样本和验证样本。由于数据集的特殊性,本实验将各个类型的数据提取出来,独自按比例拆分。
再来介绍一下KNN算法:
构造KNN分类器的过程:
(1)算距离:通过计算各个训练数据与测试数据之间的距离,按照距离递增关系排序;
(2)找邻居:选取距离最小的K个点,确定K个点所在类别的出现频率;
(3)做分类:返回前K个点中出现频率最高的类别作为测试数据的预测分类。
其中,在计算距离时选择有很多,本实验采用了比较简单的欧氏距离。
使用KNN分类器对训练样本进行模型训练。利用得到的模型对验证样本进行预测,得出预测结果,输出验证正确的样本个数,以及样本准确率。随后,对训练样本和测试样本分别进行可视化。
本实验中选择了两类特征:折射率和Na,进行测试训练。调整K值进行多次分类,选择最好的分类结果,本实验中经过多次测试选择K=17。
在对上述结果进行可视化后,经过分析可知,选取的两个特征值之间的差距有点大,所以在模型训练之前,需要把数据放到同一量级,进行数据预处理。本模型采用了数据归一化的方法,目的是把不一样的特征数据缩放到相同的一个相似区间中。随后,按照相同的步骤进行模型训练,并进行验证。

下面展示代码:

// An highlighted block
#读取数据并分类
def read_dataset():
    #读取数据
    data=pd.read_csv("C:/Users/liran/Desktop/glass.data",header=None)   data.columns=['Id','Rl','Na','Mg','Al','Si','K','Ca','Ba','Fe','Type']
    #删掉不需要的Id列
    data.drop(0,axis=1,inplace=True)
    #对数据进行去重处理
    data.drop_duplicates(inplace=True)
    #查看各个类别的玻璃各有多少条记录
    #print(data["Type"].value_counts())
    # 拆分数据集,划分为训练样本和验证样本
    # 提取出每个类别的数据
    t1 = data[data["Type"] == 1]
    t2 = data[data["Type"] == 2]
    t3 = data[data["Type"] == 3]
    t4 = data[data["Type"] == 4]
    t5 = data[data["Type"] == 5]
    t6 = data[data["Type"] == 6]
    t7 = data[data["Type"] == 7]
    # 对每个类别的数据进行洗牌 保证训练样本和测试样本取样方式相同
    t1 = t1.sample(len(t1), random_state=0)
    t2 = t2.sample(len(t2), random_state=0)
    t3 = t3.sample(len(t3), random_state=0)
    t4 = t4.sample(len(t4), random_state=0)
    t5 = t5.sample(len(t5), random_state=0)
    t6 = t6.sample(len(t6), random_state=0)
    t7 = t7.sample(len(t7), random_state=0)
    # 构建训练集和验证集
    #各自截取前70%,除最后列外的列,因为最后一列是y
    train_x=pd.concat([t1.iloc[:49,1:3],t2.iloc[:53,1:3],t3.iloc[:12, 1:3], t4.iloc[:0, 1:3], t5.iloc[:9, 1:3],t6.iloc[:6, 1:3], t7.iloc[:5, 1:3]], axis=0)
    train_y=pd.concat([t1.iloc[:49, -1], t2.iloc[:53, -1], t3.iloc[:12, -1], t4.iloc[:0, -1], t5.iloc[:9, -1],t6.iloc[:6, -1], t7.iloc[:5, -1]], axis=0)
    test_x=pd.concat([t1.iloc[49:,1:3],t2.iloc[53:, 1:3], t3.iloc[12:, 1:3], t4.iloc[0:, 1:3], t5.iloc[9:, 1:3],t6.iloc[6:, 1:3], t7.iloc[5:, 1:3]], axis=0)
    test_y = pd.concat([t1.iloc[49:, -1], t2.iloc[53:, -1], t3.iloc[12:, -1], t4.iloc[0:, -1], t5.iloc[9:, -1],t6.iloc[6:, -1], t7.iloc[5:, -1]], axis=0)
    return train_x,train_y,test_x,test_y,data
#KNN分类算法
class KNN:
    #初始化方法 k:邻居的个数
    def __init__(self, k):
        self.k = k
    #训练方法
    # X : [样本数量, 特征数量],待训练的样本特征(属性)
    # y : [样本数量],每个样本的目标值(标签)。
    def fit(self, X, y):
        # 将X转换成ndarray数组
        self.X = np.asarray(X)
        self.y = np.asarray(y)
    #根据参数传递的样本,对样本数据进行预测
    # X : [样本数量, 特征数量],待训练的样本特征(属性)
    # return:数组类型,预测的结果
    def predict(self, X):
        X = np.asarray(X)
        result = []
        # 对ndarray数组进行遍历,每次取数组中的一行。
        for x in X:
          # 对于测试集中的每一个样本,依次与训练集中的所有样本求距离。
            dis = np.sqrt(np.sum((x - self.X) ** 2, axis=1))
          # 返回数组排序后,每个元素在原数组(排序之前的数组)中的索引。
            index = dis.argsort()
           # 进行截断,只取前k个元素。【取距离最近的k个元素的索引】
            index = index[:self.k]
         # 返回数组中每个元素出现的次数。元素必须是非负的整数。            count = np.bincount(self.y[index], weights=1 / dis[index])
            # 返回ndarray数组中,值最大的元素对应的索引。该索引就是我们判定的类别。# 最大元素索引,就是出现次数最多的元素。
            result.append(count.argmax())
        return np.asarray(result)
#绘图展示测试样本,每类数据点以不同的颜色显示
def vision_train(data_x,y):
    fig = plt.figure(figsize=(10, 10))
    ax = fig.add_subplot(1, 1, 1)  # 界面只需显示一个视图
    ax.set_title('KNN separable data_train set')  #视图名称
    plt.xlabel('RI-2')    #坐标轴名称
    plt.ylabel('Na-3')
    type1_x = []
    type1_y = []
    type2_x = []
    type2_y = []
    type3_x = []
    type3_y = []
    type4_x = []
    type4_y = []
    type5_x = []
    type5_y = []
    type6_x = []
    type6_y = []
    type7_x = []
    type7_y = []
    colors = ['r','g','b','y','k','m','c']   #定义显示的颜色
    #查找样本对应类型的索引
    for i in range(213):
        #防止list index out of range的错误,使用try except
        try:
            if (y[i] == 1):
                type1_x.append(data_x.iloc[i,0])
                type1_y.append(data_x.iloc[i,1])
            elif (y[i] == 2):
                type2_x.append(data_x.iloc[i, 0])
                type2_y.append(data_x.iloc[i, 1])
            elif (y[i] == 3):
                type3_x.append(data_x.iloc[i, 0])
                type3_y.append(data_x.iloc[i, 1])
            elif (y[i] == 4):
                type4_x.append(data_x.iloc[i, 0])
                type4_y.append(data_x.iloc[i, 1])
            elif (y[i] == 5):
                type5_x.append(data_x.iloc[i, 0])
                type5_y.append(data_x.iloc[i, 1])
            elif (y[i] == 6):
                type6_x.append(data_x.iloc[i, 0])
                type6_y.append(data_x.iloc[i, 1])
            else:
                type7_x.append(data_x.iloc[i, 0])
                type7_y.append(data_x.iloc[i, 1])
        except:
            continue
    ax.scatter(type1_x,type1_y,marker='o',color='r', label='building_windows_float_processed',s=10)
    ax.scatter(type2_x,type2_y,marker='o',color='g', label='building_windows_non_float_processed', s=10)
    ax.scatter(type3_x,type3_y,marker='o',color='b', label='vehicle_windows_float_processed', s=10)
    ax.scatter(type4_x,type4_y,marker='o',color='y', label='vehicle_windows_non_float_processed', s=10)
    ax.scatter(type5_x,type5_y,marker='o',color='k', label='containers', s=10)
    ax.scatter(type6_x,type6_y,marker='o',color='m', label='tableware', s=10)
    ax.scatter(type7_x,type7_y,marker='o',color='c', label='headlamps', s=10)
    plt.legend(loc = 'upper right')   #图例显示位置
    plt.show()
#验证样本可视化
def vision_test(test_x,test_y,result):
    right = test_x[result == test_y]
    wrong = test_x[result != test_y]
    fig = plt.figure(figsize=(10, 10))
    ax = fig.add_subplot(1, 1, 1)  # 界面只需显示一个视图
    ax.set_title('KNN separable data_test set')  # 视图名称
    plt.xlabel("RI-2")
    plt.ylabel("Na-3")
    ax.scatter(x=right.iloc[:, 0], y=right.iloc[:, 1], color='r', marker="x", label="right",s=10)
    ax.scatter(x=wrong.iloc[:, 0], y=wrong.iloc[:, 1], color="m", marker=">", label="wrong",s=10)
    plt.legend(loc="upper right")
    plt.show
# 归一化特征值  特征缩放
def autoNorm(dataSet):
    #求最大值和最小值
    #X_new=(x-min)/(max-min)
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(np.shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet / np.tile(ranges, (m, 1))
    return normDataSet, ranges, minVals
def main():
    #读取数据
    train_x,train_y,test_x,test_y,data = read_dataset()
    # 创建KNN对象,进行训练和验证
    knn = KNN(k=17)
    # 进行训练
    knn.fit(train_x, train_y)
    # 进行验证
    result = knn.predict(test_x)
    #输出测试正确个数及正确率
    print(sum(result == test_y))
    print(sum(result == test_y)/len(result))
    #pandas读取的数据要转换成list之后再进行查找索引操作
    trainy = train_y.values.tolist()
    #进行可视化
    #训练样本可视化
    #vision_train(train_x,trainy)
    #测试样本可视化
    #vision_test(test_x,test_y,result)
    #归一化处理数据
    data_x,ranges,minVals=autoNorm(train_x)
    knn1 = KNN(k=17)
    knn1.fit(data_x,train_y)
    result = knn1.predict(test_x)
    # 输出测试正确个数及正确率
    print(sum(result == test_y))
    print(sum(result == test_y) / len(result))
    #归一化后的可视化
vision_train(data_x,trainy)

if __name__ == '__main__':
    main()
评论 4 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

小小小姝

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值