zoukankan      html  css  js  c++  java
  • K-means实现二分类问题

    最近做一个有关二分类问题,我打算使用K-means算法实现baseline。

    首先,我的数据文件形式是“.arff”格式的,在处理这种数据格式的时候,我是花了一些精力的,话不多说,代码如下:

    import numpy as np
    
    def readarff(filename):
        #dataMat=np.zeros(shape=(1000,4096))
        dataMat=[[0 for i in range(4096)] for j in range(591)]
        arff_file=open(filename)
        lines=arff_file.readlines()
        count=0
        for l in lines:
            content=[]
            if not (l.startswith("@")):
                content.append(l)
                for c in content:
                    cs=c.split(',')
                    cs.pop(0)
                    cs.pop(0)
                    cs.pop(0)
                    flag=True
                    while flag:
                        temp=cs[0].split(' ')
                        index=int(temp[1])
                        if not(index==4099):
                            dataMat[count][index-3]=(float)(temp[2])
                            #print count
                            #print index-4
                            cs.pop(0)
                        else:
                            flag=False
            count=count+1
        dataMat=np.matrix(dataMat)
        return dataMat
    
    
    dataMat=readarff('data/temp1.arff')

    我的数据文件中,前三个属性是不应该作为特征属性的,这就是出现了三个pop()的原因。

    dataMat是一个数据矩阵,这个矩阵也是最后需要的一个返回值。关于这个矩阵,在初始化时,一定要使用:

    dataMat=[[0 for i in range(4096)] for j in range(591)]

    这种形式,而不要使用:

    dataMat=[[0]*4096]*591

    因为,如果使用下面这种形式的话,在给矩阵赋值的时候,例如:

    dataMat[0][0]=0.123456

    这样改变的不只是(0,0)这一个位置的值,而是会改变所有行的第0列的值。(具体知识点涉及到了list的浅拷贝问题,可以参照:https://www.cnblogs.com/btchenguang/archive/2012/01/30/2332479.html)

    另外,由于我的数据格式是“ 1 0.123456789”,第二个数字才是我需要的,这也就是我为什么使用split对空格进行分割的原因了。

    还有一个注意点:

    就是我的强制类型转换那一步:

    dataMat[count][index-3]=(float)(temp[2])

    这里如果不进行强制类型转化,会发现在后面进行K-means算法时,数据之间的运算会出问题,这是因为,这个矩阵中数据类型是unicode型的。

    下面就是K-means算法了:

    #计算欧几里得距离
    def
    distEclud(vecA,vecB): return sqrt(sum(power(vecA-vecB,2))) # 计算两个向量之间的距离
    #随机生成k个质心
    def randCent(dataSet,k): #n=shape(dataSet)[1] n=dataSet.shape[1] centroids=mat(zeros((k,n))) for j in range(n): minJ=min(dataSet[:,j]) maxJ=max(dataSet[:,j]) rangeJ=float(maxJ-minJ) #这一步就是上面说的如果不进行强制类型转换会出现问题的位置 centroids[:,j]=minJ+rangeJ*random.rand(k,1) return centroids
    #k-means算法:
    def kMeans(dataSet,k,distMeans=distEclud,createCent=randCent): m=dataSet.shape[0] clusterAssment=mat(zeros((m,2))) #存放该样本属于哪类,以及距质心的距离 centroids=createCent(dataSet,k) clusterChanged=True while clusterChanged: clusterChanged=False; for i in range(m): minDist=inf;minIndex=-1; for j in range(k): distJI=distMeans(centroids[j,:],dataSet[i,:]) if distJI<minDist: minDist=distJI;minIndex=j if clusterAssment[i,0]!=minIndex:clusterChanged=True; clusterAssment[i,:]=minIndex,minDist**2 print(centroids) #在每一轮迭代后都输出一次质心的坐标
          #更新质心点的坐标
    for cent in range(k): ptsInClust=dataSet[nonzero(clusterAssment[:,0].A==cent)[0]] centroids[cent,:]=mean(ptsInClust,axis=0) return centroids,clusterAssment datMat=mat(readarff('data/temp1.arff')) myCentroids,clustAssing=kMeans(datMat,2) print(myCentroids) print(clustAssing)

    K是类别的个数,这里我定为了2,;具体情况可以自己改变。

  • 相关阅读:
    初学者常用的LINUX命令
    logging模块全总结
    logging模块初识
    xpath知多少
    selenium常用的API
    系统测试基础(适合入门)
    JavaScript正则表达式(一)
    webpack2学习(二)
    webpack2学习(一)
    SQL语句学习
  • 原文地址:https://www.cnblogs.com/kennqiang/p/10027368.html
Copyright © 2011-2022 走看看