接上一篇,使用 oneR算法来实现iris分类. 

# coding: utf-8  
#使用oneR算法来实现iris分类
#参考:   http://www.cnblogs.com/htynkn/archive/2012/04/14/2446905.html
#算法思路: 根据已有数据中,具有相同特征值的个体最可能属于哪个类别进行分类.
#oneR是one rule(一条规则)的简写, 表示只选取四个特征中分类效果最好的一个用作分类的依据. 
#步骤:
    #1. 离散化特征值: 因为oneR算法使用类别型特征值,而原数据集为连续值。因此需要把连续值转为类别型
        #简单的离散方法: 设定一个阈值,将低于该阈值的特征值置为0,高于阈值的置为1.  某特征的阈值设定为该特征所有特征值的均值.
    #2. 遍历每个特征的每一个取值,对于每一个特征值,统计它在各个类别中的出现次数。找到它出现次数最多的类别,并统计它在其它类别中的出现次数.
    #3. 统计完所有的特征值及其在每个类别的出现次数后,再计算每个特征的错误率。计算方法为把它的各个取值的错误率相加,选取错误率最低的特征作为唯一分类准则,用于接下来的分类
    

import numpy as np
from sklearn import datasets
iris=datasets.load_iris()
x=iris.data
y=iris.target
n_samples,n_features=x.shape    #  结果为: (150,4) 取出数据行数及列数

#计算每个特征列的均值
attribute_means=x.mean(axis=0)   #axis=0表示列    1表示行   
#以上结果为 :  array([ 5.84333333,  3.054     ,  3.75866667,  1.19866667]) 
#将上面的结果转为一个数组,这个数组正好是四列,分别对应了四个特征值的均值,再用这个均值做阈值将数据集打散,将连续的特征值转为类别型,即完成步骤一
x_d=np.array( x>=attribute_means, dtype='int')

#接下来切分训练集和测试集, 切分数据集为训练集和测试集
#方案一: 像上一个案例一样,切成140:10的比例
#np.random.seed(0)
# permutation函数: 随机排列   https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.permutation.html
#i=np.random.permutation(len(x_d))
#训练集: 取出打乱后的前140条数据
#x_train=x_d[i[:-10]]   #前140条数据
#y_train=y[i[:-10]]   #前140条数据对应的花的类型
#输出x_train, y_train
#x_train
#y_train
#测试集
#x_test=x_d[i[-10:]]   #最后10条数据
#y_test=y[i[-10:]]   #最后10条数据对应的花的类型
#方案2: 利用 scikit-learn库提供的切分函数
from sklearn.cross_validation import train_test_split
#train_test_split知识 :  http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.train_test_split.html
x_train,x_test,y_train,y_test=train_test_split( x_d,y,random_state=14)
print("{} training samples".format(x_train.shape))
print("{} testing samples".format(y_test.shape))




from collections import defaultdict   # http://www.pythontab.com/html/2013/pythonjichu_1023/594.html
from operator import itemgetter       # http://www.cnblogs.com/100thMountain/p/4719503.html

#定义一个函数: 遍历数据集中每一条数据,统计具有给定特征值的个体在各个类别中的出现次数
            # 参数说明:   数据集 类别数组 选好的特征索引值 特征值
def train_feature_value( X, y_true, feature_index, value):
    class_counts=defaultdict(int)
    #zip函数用法:  http://www.cnblogs.com/frydsh/archive/2012/07/10/2585370.html
    for sample,y in zip(X, y_true):
        if sample[feature_index]==value:
                class_counts[y]+=1
    #对class_counts字典排序,找到最大值,这就找到了具有给定特征值的个体在哪个类别中出现次数最多
    sorted_class_counts=sorted(class_counts.items(), key=itemgetter(1),reverse=True)
    most_frequent_class=sorted_class_counts[0][0]
    #计算该条规则错误率
    error=sum(  [ class_count for class_value,class_count in class_counts.items() if class_value!=most_frequent_class ])
    return most_frequent_class,error
    
    
#定义另一个函数:
    #对于某项特征,遍历其每一个特征值,调用上面的函数,就能得到预测结果和每个特征值所带来的错误率,然后把所有错误率累加起来,就能得到该特征的总错误率。
def train(X,y_true,feature_index):
    #以数组形式返回由feature_index所指的列的值.然后以set函数将数组转为集合. 
    values=set(X[:,feature_index])
    #再创建字典
    predictors=dict()
    errors=[]
    for current_value in values:
        most_frequent_class,error=train_feature_value( X,y_true, feature_index, current_value)
        predictors[current_value]=most_frequent_class
        errors.append( error )
    #最后计算该规则的总错误率
    total_error=sum(errors)
    return predictors,total_error
    

#计算预测器
all_predictors={variable:train(x_train,y_train,variable) for variable in range(x_train.shape[1])}
errors={variable:error for variable, (mapping,error) in all_predictors.items()}

#找出错误率最低的特征,作为分类的唯一规则
best_feature,best_error=sorted(errors.items(),key=itemgetter(1))[0]
#对预测器进行排序,找到最佳特征值,创建模型
model={'feature':best_feature,'predictor':all_predictors[best_feature][0]}
#model中的元素,一个用于分类的特征和预测器
#下面可以开始对测试集进行预测了

#首先定义一个函数
def predict( x_test,model):
    feature=model['feature']
    predictor=model['predictor']
    y_predicted=np.array([predictor[int(sample[feature])] for sample in x_test])
    return y_predicted
    
#调用上面的函数对测试集进行预测
y_predicted=predict( x_test,model)
#使用模型预测的结果:  array([0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0,
  #     2, 0, 2, 0, 2, 2, 0, 0, 0, 2, 0, 2, 0, 2, 2])

y_test
#标准结果: array([0, 0, 0, 1, 2, 1, 0, 1, 0, 1, 2, 0, 2, 2, 0, 1, 0, 2, 2, 1, 0, 0, 0,
 #      1, 0, 2, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 2, 1])

#计算正确率
accuracy=np.mean( y_predicted==y_test)*100
print(u"模型正确率为:{:.1f}%".format( accuracy))   # 65.8%

最后使用测试集进行测试,正确率为 65.8%.   对于这样一条简单的规则来说,已经非常不错了. 
Logo

永洪科技,致力于打造全球领先的数据技术厂商,具备从数据应用方案咨询、BI、AIGC智能分析、数字孪生、数据资产、数据治理、数据实施的端到端大数据价值服务能力。

更多推荐