Pandas優(yōu)化OneRule算法

《Python數(shù)據(jù)挖掘入門與實踐》第一章第五節(jié)(1.5)中關于分類問題提到了一種簡單實用的分類算法——OneR算法。
其實現(xiàn)方式多少有點麻煩,本人不才,用Pandas庫用對其代碼進行了優(yōu)化,這里介紹了兩者優(yōu)化的方式。
(什么是OneR算法?戳這里http://blog.csdn.net/baidu_25555389/article/details/73379036

本次所有代碼的運行環(huán)境均為Anoconda的jupyter notebook。

方法一,在作者思路上進行優(yōu)化

作者的思路是首先創(chuàng)建一個函數(shù),給定這個函數(shù)數(shù)據(jù)集,特征類,特征值,即可計算出這個特征值所對應因變量類別出現(xiàn)的次數(shù),并進行錯誤率或者準確率計算。

這里用的數(shù)據(jù)是經(jīng)典的“鳶尾花”數(shù)據(jù),其數(shù)據(jù)可以直接再scikit-learn庫中進行導入。特征主要有四個:'萼片長度','萼片寬度', '花瓣長度', '花瓣寬度'。

因變量y有三個類別分別為'山鳶尾','變色鳶尾','維吉尼亞鳶尾'

每個特征值均為連續(xù)變量,首先將其以均值為分解點,將每個特征劃分為兩類(高低兩類)。

1、導入數(shù)據(jù)
from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
# 導入數(shù)據(jù)
dataset = load_iris()
x = dataset.data
y = dataset.target

# 導入pd的dataframe
df = pd.DataFrame(x,columns=['x%s'% str(i+1)  for i in range(4)])
df['y'] = pd.Series(y)
df.head()
df.describe().round(3)
數(shù)據(jù)基本內(nèi)容.png
2、將特征值離散化
# 以均值對每個特征進行區(qū)分,遍歷每個值與均值做個減法
df = df.assign(sl=lambda x : x.x1 - x.x1.mean())
df = df.assign(sw=lambda x : x.x2 - x.x2.mean())
df = df.assign(pl=lambda x : x.x3 - x.x3.mean())
df = df.assign(pw=lambda x : x.x4 - x.x4.mean())

# 將每個自變量的值與0進行比較
df2 = df.iloc[:,5:].round(3) > 0
df2['y'] = pd.Series(y)

# 將大于0的True設置為1,將小于0的Fales設置為0
dict_map = {
    False:0,
    True:1
}

# 遍歷每一列用map方法進行轉換
for i in range(4):
    df2.iloc[:,i] = df2.iloc[:,i].map(dict_map)
df2.head()
離散化后的數(shù)據(jù)

其中sl,sw,pl,pw分別代表離散處理后的'萼片長度','萼片寬度', '花瓣長度', '花瓣寬度'。

3、將數(shù)據(jù)集劃分為訓練集和測試集
from sklearn.model_selection import train_test_split
X, y =  df2.iloc[:,:4],df.iloc[:,4].values
X_train, X_test, y_train, y_test = train_test_split(X, y ,test_size = 0.25, random_state = 0)
4、定義類別統(tǒng)計函數(shù)
# 自定義一個函數(shù),統(tǒng)計具有給定特征值的個體在各個類別中出現(xiàn)的次數(shù),并以datafranme的形式返回。
def train_feature_value(X, y, feature_index, feature_val):
    # 給index和columns定義基礎值
    feature = {
        0 : '萼片長',
        1 : '萼片寬',
        2 : '花瓣長',
        3 : '花瓣寬',
    }
    values = {
        0 : ' -- 低',
        1 : ' -- 高',
    }
    # 設置初始dataframe
    df_error = pd.DataFrame(np.zeros((1,3)),
                            index=[feature[feature_index]+values[feature_val]],
                            columns=['山鳶尾','變色鳶尾','維吉尼亞鳶尾'])
    # 遍歷,尋找,增加
    for sample, i in zip(X.iterrows(),y):
        if sample[1][feature_index] == feature_val:
            df_error.iloc[0,i] += 1
    return df_error
4、遍歷所有特征并計算
frames = []
for i in range(4):
    for j in range(2):
        df_error = train_feature_value(X_train,y_train,i,j)
        frames.append(df_error)
# 將所有的datafram合并
result = pd.concat(frames)

result
各個特征值所對應的類別數(shù)量
5、遍歷每個特征,并計算所對應每個類別的準確率
for i in range(len(result)):
    result.iloc[i] = result.iloc[i]/result_sum[i]
result.round(3)
所有特征所對應類別的準確率

由此可以得到每個類別的鳶尾花所對應的主要特征,其中山鳶尾所對應的唯一特征是,花瓣長度值低;變色鳶尾所對應唯一特征為萼片寬度低;維吉尼亞鳶尾所對應的唯一特征為萼片長度高;

用max方法可以快速查看
6、選取花瓣長度,來預測山鳶尾
X_test['y'] = X_test['pl']
true_counts = 0
for i , j in zip(X_test.iloc[:,4],y_test):
    if i == j:
        true_counts += 1
print('預測準確率為%.2f%%' % (true_counts/len(y_test)*100))

最終預測準確率為73.68%。雖然準確率并不高,但考慮到只用到了一個特征, 這個結果已經(jīng)很理想了。

方法二,用交叉表直接得到特征類別數(shù)量表

運用Pandas自帶的crosstab方法可以快速計算類別特征數(shù)量

X_train['y'] = y_train
train_data = X_train
feature = {
    0 : '萼片長',
    1 : '萼片寬',
    2 : '花瓣長',
    3 : '花瓣寬',
}
values = {
    0 : ' -- 高',
    1 : ' -- 低',
}
frames2 = []
for i in range(4):
    df2=pd.crosstab(train_data.iloc[:,i],train_data.iloc[:,4])
    frames2.append(df2)
df4 = pd.concat(frames2)
df4['index'] = result.index
df4.columns = ['山鳶尾','變色鳶尾','維吉尼亞鳶尾','index']

df4.set_index('index')
特征類別統(tǒng)計表

第二種方法比較簡單直接,計算出統(tǒng)計表以后再用前面代碼進行準確率計算,提取主要特征,進行預測即可,在此不作贅述。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容