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,;具體情況可以自己改變。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM