onehot在python(sklearn)中的使用方法,示例,代碼實現

首先強調一下,本篇博客是我實驗得出來的結論,要是錯了,可以在評論區指正,嘻嘻

接下來我會介紹以下三個內容

  • 爲什麼要用onehot
  • 怎麼用

爲什麼要用onehot:

 假設你有一個這樣的數據集,格式是csv或者arff格式:

體重 身高 ... class
1 5 0 ... 不好看
1 6 0 ... 還可以
有點胖 1 8 0 ...
有點瘦 1 5 0 ... 還可以

你現在需要對這個數據構建一個分類器,挖掘一些有用的信息,此時你想到了sklearn(真是個錯誤的決定),你會發現如果你把這個數據集直接當成數據矩陣numpy,輸入sklearn中的分類器中,編譯器會提示你,類型錯誤,無法把string(或者btype)類型轉成float....

經過我查閱多方資料,我才明白,原來sklearn中的數據默認得是全數值類型。一個非常好又不方便的設定,在:統一數據類型,不方便在:有得時候我們的數據就是數值,離散值,string類型混合的。那我們就來解決吧(當然,如果你換weka(java)這個機器學習庫就沒有這種奇怪的問題)


怎麼用:

在講怎麼寫onehot代碼之前,我先簡單介紹一下onehot方法,簡單地說,onehot方法可以把剛剛上面的這個數據變成這個樣子:

 

是否胖 是否瘦 是否有點胖 是否有點瘦 身高 ... class
1 0 0 1 5 0 ... 不好看
0 1 0 0 1 6 0 ... 還可以
0 0 1 0 1 8 0 ...
0 0 0 1 1 5 0 ... 還可以

從上面的數據,我們可以發現,onehot方法就是把離散取值(取名詞)的屬性裂變成多個屬性(取值爲01),這樣就可以給sklearn計算了。

好的,接下來,我展示一下,具體的代碼(使用onehot重新編碼,並進行knn分類,然後返回十折交叉驗證結果的代碼)調用示例:

def do_knn(fea,lab,k):
    # sdata=fea+lab
    auc=0
    #x是個矩陣
    #arffdata = imp.fit_transform(arffdata)
    #lab.reshape(-1,1).reshape(-1)#?????去掉它的多餘括號
    flo = []  # 存放數值型屬性
    str = []  # 存放名詞性屬性
    colmn = fea.shape[1]  # 存放列數
    raw = fea.shape[0]  # 存放行數
    strnumber = 0#判斷是否存在名詞性屬性
    flonumber=0
    for i in range(colmn):
        if type(fea[0][i]) == bytes or type(fea[0][i]) == np.bytes_:
            str.append(fea[:, i])
            strnumber += 1
        else:
            flo.append(fea[:, i])
            flonumber+=1
    flo = np.array(flo).T
    str = np.array(str).T

    features=np.random.rand(1)#之後重新賦值
    if strnumber != 0 and flonumber != 0:
        enc = OneHotEncoder()
        enc.fit(str)
        str = enc.transform(str).toarray()
        str = np.array(str)
        features = np.concatenate((flo, str), 1)
    if strnumber==0:
        features = flo
    if flonumber==0:
        enc = OneHotEncoder()
        enc.fit(str)
        str = enc.transform(str).toarray()
        features = np.array(str)
    knn = KNeighborsClassifier(n_neighbors=k)
    scores = cross_val_score(knn, features, lab, cv=5, scoring='accuracy')
    auc=sum(scores)/len(scores)
    #print(lab)#似乎是因爲btype類型的原因
    return auc###auc有時居然是空的

代碼片段有點長,那是因爲這個方法用起來真的不方便(以前的版本是很方便,只需要一行就能實現,後來sklearn把一個關鍵的函數去掉了。。)

代碼解釋說明:這個函數是計算一組數據進行knn分類方法並返回十折交叉驗證的平均auc的函數。輸入的fea是數據的特徵(屬性),輸入的lab是數據的類別,所以這段代碼是對fea進行數值化處理的。

關鍵的代碼是這個:

enc = OneHotEncoder()
enc.fit(str)
str = enc.transform(str).toarray()
features = np.array(str)

首先,創建一個onehotencoder對象(方法),然後讓這個方法去學str(把fea的所有非數值類取出來,存放在str中)矩陣中的信息(每個屬性的取值有幾種),再通過transfrom函數就可以把非數值得矩陣轉成純數值的數據矩陣。


補充說明:

上面的代碼中,我先對數據集的屬性矩陣進行了一個評定,看看這個數據的屬性含不含非數值類型,並把數值型屬性和非數值屬性分開,最後調用onehot方法把非數值屬性的矩陣轉成純數值矩陣,最後再把這兩個矩陣拼接,構成數據集的完整屬性矩陣features,最後利用這個featurs和lab得到了分類的結果。

我這麼做的原因是因爲,onehot方法以前的版本是可以選擇哪一列需要數值化 的,方法是這樣 enc=onehotencoder(categories
_featuires=[1,2]),這樣的onehot就可以一行實現一個數據矩陣中的第一列和第二列數值化,真的是很方便,但是,不知道爲什麼,我這個版本把這種這麼好的輸入參數去掉了。。。。。。。所以他默認就是全部數值化,這樣就會導致,如果你有一個屬性是身高,取值有148.2,145.6,170.9等等,那麼他就會裂變出 是否148.2,是否145.6.......這麼多屬性。。。。。所以我才做得這麼麻煩。

要是你們知道怎麼快速進行onehot方法(可以選擇那一列裂變),可以在評論區告訴我呀,感謝感謝

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章