机械学习使用兰氏距离的最小距离聚类法以及散点图展示

最短距离聚类法的原理

相信大家都应该明白聚类算法的含义,所谓的最短距离聚类法,就是在给出n个距离中心的情况下分别将文本中的待训练数据和他们通过某种方式进行计算距离,这里是兰氏距离,当然也可以是欧式距离,曼哈顿距离。然后找出改点对那n个店最短的那个距离,改点就属于那个聚类中心的类别。打个比方 现在有四个聚类中心a,b,c,d 我现在有个点叫fk 那么现在fk通过某个距离算法得出和a的距离小于b,c,d的距离 那么fk就属于a类

实现步骤:

1.数据最大最小值归一化处理,也可以是标准化处理

1.首先是把距离中心先放入存入到center的二维列表中,然后通过最大值和最小值归一化进行划分数据。本程序中有两种方法进行:第一种是纯手写版本:利用公式:
先求出样本数据中的最大值和最小值,然后通过公式求出其归一化后数据然后再返会要处理的数据列表,并且也求出了数据样本里面的正确类别放入lss列表中
以便于后面分析分类精确度进行对比
其中我将类别英文名字进行数字代表:
**
类别代表 :Slight-Right-Turn:1 Move-Forward:2 Sharp-Right-Turn:3 Slight-Left-Turn:4**
代码如下:

def  maxandmin_stand2():#非库函数版本 最大值最小值归一化
    fr = open("data.txt")
    numberOfLines = len(fr.readlines());
    returnMat = zeros((numberOfLines,2))
    classLabelset=[]
    fr =open("data.txt")
    index=0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split(',')
        returnMat[index,:]=listFromLine[0:2]
        index+=1

库函数版本则是
利用库函数实现类的转换器,利用fit_transform后面的会发全部实现过程
函数处理
代码:
def maxandmin_stand(data,lss):#采用最大最小值归一化并且拼接好类别代表(库函数版本)

    # 1、实例化一个转换器类
    transfer = MinMaxScaler(feature_range=(0, 3))
    # 2、调用fit_transform
    data = transfer.fit_transform(data)
    # print("最小值最大值归一化处理的结果:\n", data)
    i = 0;
    listall = []
    for string in data:
        string = np.append(string, lss[i])
        i = i + 1
        listall.append(string)
return listall,data

图中列表为归一化后数据

这个列表为归一化后库的标准数据。

一共871条和data.txt数据吻合

2 数据预处理完毕后进行分类(兰氏距离)

主要公式是d += abs(x[i] - y[i]) / (abs(x[i]) + abs(y[i]))(兰氏距离)
首先传入的数据是最大最小值归一化后的二维列表数据和距离中心,通过计算样本数据和距离中心的兰氏距离,然后对比改点和四个距离中心哪个点最近,从而确定该点属于哪一类。并且返会进行分类后的数据列表temp代码如下

该阶段分析截图 关键是计算点与距离中心间的兰氏距离:兰氏距离我的理解是两点间的距离为二维对应xy的绝对值的差和之比然后进行累加:我这个二维列表所以是两个维度算完相加
d += abs(x[i] - y[i]) / (abs(x[i]) + abs(y[i]))兰氏距离
机械学习使用兰氏距离的最小距离聚类法以及散点图展示_第1张图片

然后是返会列表和标准数据对比分析分类的正确率和错误率

analycisrate(classdata,lss)#calcdata 和 classdata 是分类后的数据和类别lss是样本标准数据
代码如下:

def analycisrate(classdata,standdata):#分析正确率
    #print(standdata)
    lens = len(standdata)
    count=0
    for i in range(lens):
        temp=int(standdata[i])-int('0')
        if classdata[i] == temp:
            count=count+1;
    right=count/lens*100.0
    falut=(1-count/lens)*100.0
print("正确率为:"+str(right)+"%\n错误比率为:"+str(falut)+"%")

3.最后就是画出散点图shows函数完成

在shows函数里面我将不同类的二维数据变成x,y坐标,然后不同的类别进行不同的颜色点描述
机械学习使用兰氏距离的最小距离聚类法以及散点图展示_第2张图片

总的代码

import numpy as np
from matplotlib import pyplot as plt
from numpy import zeros
from sklearn.preprocessing import MinMaxScaler
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
import numpy as np
mpl.rcParams['font.sans-serif'] = ['SimHei']
import numpy
## 类别代表 :Slight-Right-Turn:1  Move-Forward:2   Sharp-Right-Turn:3  Slight-Left-Turn:4

def sconvert(s):
  ss=""
  if s == "Slight-Right-Turn\n":
        ss+='1'

  if s == "Move-Forward\n":
         ss+='2'

  if s == "Sharp-Right-Turn\n":
         ss = '3'

  if s == "Slight-Left-Turn\n":
         ss='4'
  return ss


def  maxandmin_stand2():#非库函数版本z最大值最小值归一化
    fr = open("data.txt")
    numberOfLines = len(fr.readlines());
    returnMat = zeros((numberOfLines,2))
    classLabelset=[]
    fr =open("data.txt")
    index=0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split(',')
        returnMat[index,:]=listFromLine[0:2]
        index+=1
    return  returnMat

def maxandmin_stand(data,lss):#采用最大最小值归一化并且拼接好类别代表(库函数版本)
    # 1、实例化一个转换器类
    transfer = MinMaxScaler(feature_range=(0, 3))
    # 2、调用fit_transform
    data = transfer.fit_transform(data)
    # print("最小值最大值归一化处理的结果:\n", data)
    i = 0;
    listall = []
    for string in data:
        string = np.append(string, lss[i])
        i = i + 1
        listall.append(string)
    return listall,data#


def SplitdataArray():#分割txt里面的数据数组
    file = open('data.txt')
    val_list = file.readlines()
    lss = []
    numlists = []
    for string in val_list:
        string = string.split(',', 3)
        lss.append(sconvert(string[2]))
        numlists.append(string[0:2])  # 取替换后得到的前两项,得到的最大最小归一化即为所要的列表

    # print(lists)
    return lss
#下标和类别转换函数
def convertlabal(index):
    labal=""
    if index == 1:
        labal="Slight-Right-Turn"
    if index == 2:
        labal="Move-Forward"
    if index == 3:
        labal ="Sharp-Right-Turn"
    if index == 4:
        labal = "Slight-Left-Turn"
    return labal


def classify0(calcdata, center):#calcdata待计算的样本数据点,center为类别中心
    # dataSet.shape[0] :第一维的长度(行);dataSet.shape[1] :第二维的长度(列)
    dataSetSize = center.shape[0]
    calcdatasize= calcdata.shape[0]
    #print(dataSetSize,calcdatasize)查看行数对不对
    dis=[]
    nums=[]
    for i in range(dataSetSize):
        for j in range(calcdatasize):#d += abs(x[i] - y[i]) / (abs(x[i]) + abs(y[i]))兰氏距离
            num=0
            for k in range(2):
              #print(k)
              num+=(abs(calcdata[j][k]-center[i][k]) /(abs(calcdata[j][k])+abs(center[i][k])))
            #print("第 " + str(i+1) + "个中心和" + str(j+1) + "样本兰氏距离为:" + str(num))
            nums.append(num)

        dis.append(nums)
        nums=[]

    #print(dis[3])
    count=0
    temp=[]#临时的拼接数组
    temps=[]#分类距离最近的类别

    for i in range(calcdatasize):
        for j in range(dataSetSize):  # 分类
          #print(dis[j][i])
          temp.append(dis[j][i])
        temps.append(np.argmin(temp)+1)
        temp=[]
    return temps

def analycisrate(classdata,standdata):#分析正确率
    #print(standdata)
    lens = len(standdata)
    count=0
    for i in range(lens):
        temp=int(standdata[i])-int('0')
        if classdata[i] == temp:
            count=count+1;
    right=count/lens*100.0
    falut=(1-count/lens)*100.0
    print("正确率为:"+str(right)+"%\n错误比率为:"+str(falut)+"%")



def diversecalcdata(calcdata):
    lens=len(calcdata)
    x=[]
    y=[]
    for i in range(lens):
        x.append(calcdata[i][0])
        y.append(calcdata[i][1])
    return x,y

def shows(x,y,classdata):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_title('Scatter Plot')
    colors = ['b', 'g', 'r', 'orange']
    Label_Com = ['Slight-Right-Turn', ' Move-Forward',' Sharp-Right-Turn', 'Slight-Left-Turn']## 类别代表 :Slight-Right-Turn:1  Move-Forward:2   Sharp-Right-Turn:3  Slight-Left-Turn:4
    tempx=[]
    tempy=[]
    ansx=[]
    ansy=[]
    lens=len(classdata)
    for i in range(4):
        for j in range(lens):
              if (i+1) == classdata[j]:
                  tempx.append(x[j])
                  tempy.append(y[j])
                  # if x[j]>4 or y[j]>4:
                  #    print(x[j],y[j])


        ansx.append(tempx)
        ansy.append(tempy)
        tempx=[]
        tempy=[]

    for i in range(4):
     plt.scatter(ansx[i],ansy[i],s=16.,c=colors[i],  marker='8')



    plt.ylim(0, 6)
    plt.xlim(0, 6)


    plt.xlabel('X')
    plt.ylabel('Y')
    # added this to get the legend to work
    handles, labels = ax.get_legend_handles_labels()
    ax.legend(handles, labels=Label_Com)
    plt.show()


if __name__ == '__main__':
    center=[[1.687,0.445,1],
      [0.914,0.632,2],
      [0.898,0.569,3],
      [1.308,0.923,4]]
    calcdata=[]#归一化数据后的数据,data为归一后的分类好的数据
    lss=SplitdataArray()#lss为类别数据

    #data,calcdata=maxandmin_stand(data,lss)
    calcdata = maxandmin_stand2()
    #print(lss)
    #print(len(lss))
    classdata=classify0(np.array(calcdata),np.array(center))
    #print(lss)

    analycisrate(classdata,lss)#calcdata 和 classdata 是分类后的数据和类别lss是样本标准类别数据
    x,y=diversecalcdata(calcdata)#得到分类后的x,y坐标集合便于画图
    #print(len(classdata))
    shows(x,y,classdata)

数据链接和源码我全部放在百度云盘了

https://pan.baidu.com/s/1d4fNJFAsBADkOB974KwSZA
提取码1234

你可能感兴趣的:(机械学习,聚类,机器学习,python)