数据挖掘系列笔记(2)——分类规则 ONERULE方法

本文介绍了一种简化分类模型的ONER算法,并使用Iris植物分类数据集进行实验,通过离散化处理和特征错误率计算,找到了最佳分类特征。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

课本内容回顾:

分类是数据挖掘领域为常用的方法之一,不论是实际应用还是科研,都少不了它的身影。对于分类问题,我们通常能拿到表示实际对象或事件的数据集,我们知道数据集中每一条数据所属的类别,这些类别把一条条数据划分为不同的类。

数据处理在这里的目标就是根据已有的数据训练分类模型,然后可以用以对新样本的分类

实验内容:使用著名的Iris植物分类数据集:集共有150条植物数据,每条数据都 给出了四个特征:sepal length、sepal width、petal length、petal width(分别表示萼片和花瓣的长 与宽),单位均为cm)。该数据集共有三种类别:Iris Setosa(山鸢尾)、Iris Versicolour(变色鸢尾)和Iris Virginica(维吉尼 亚鸢尾)。我们这里的分类目的是根据植物的特征推测它的种类。抽象来说,就是根据已有的植物特征(4维数组)和所属分类(0,1,2)来对新的4维数组输出一个分类值。

数据获取:

scikit-learn库内置了该数据集,可直接导入。 
from sklearn.datasets import load_iris 
dataset = load_iris() 
X = dataset.data 
y = dataset.target 

数据集的特征值都是连续的,对于连续数据有个特征:差越小意味着更加相似,比如身高174和175就是很接近的数据,但是对于更多数据样本中的离散值,每个数据只是代表一个离散情况,差小不会有显然的相似关系,比如学号1和学号2的两个同学。连续值的处理更加复杂,这里为了简化代码和算法,选择将连续值先离散化进行处理。

离散方法为:

n_samples, n_features = X.shape #确定数据的维度
attribute_means = X.mean(axis=0)    #求每个横坐标的均值:特征均值
assert attribute_means.shape == (n_features,)    # 断言
X_d = np.array(X>=attribute_means, dtype = 'int')    #构建离散数据样本:大于均值为1,否则为0

这样我们就获得了离散数据样本。

接下来正是进入算法的构造:ONER原则,即“一条规则”算法,核心原理是简化模型,使用一个最能代表类别的特征值来直接判断属于哪个类别。举个例子,我们要区分一堆学生的男女,我们只要看他们生理构造就基本够了,不需要关注其他的诸如肤色等的特征。算法的训练过程就是计算使用每一个特征值作为判断依据的错误率,然后使用错误率最低的特征值。可以预见的是,如果样本数据存在一个很具有代表性的特征值,这个方法会很好用。

1. 构建函数就算每个特征值预测的错误率

def train_feature_value(X, y_true, feature_index, value): 
    class_counts = defaultdict(int)    # 统计特征值为Value的每种分类的数量
    # 比如我们说统计100个学生中有丁丁(feature(JJ).value = 1)人中,男生多少人,女生多少人
    for sample, y in zip(X, y_true):    #zip函数,把两个集合按照id顺序构建pair,做新序列
        if sample[feature_index] == value:
            class_counts[y] += 1
    
    # 排序特征值为value的样本所属分类的ID
    sorted_class_counts = sorted(class_counts.items(), key=itemgetter(1), reverse = True)
    most_frequent_class = sorted_class_counts[0][0]
    #print(sorted_class_counts)[0]
    # 根据实际结果计算分类错误的合计(有50个人JJ.value = 1,但是只有48个男生,error2个)
    error = sum([class_count for class_value, class_count in class_counts.items() if class_value != most_frequent_class])
    
    return most_frequent_class, error

接下来需要把训练函数写到循环里:(对于每个feature,得到一个预测列表和错误合计)

def train(X, y_true, feature):
    n_samples, n_features = X.shape
    assert 0<=feature<n_features
    values = set(X[:,feature])
    predictors = dict()
    errors = []
    for current_value in values:
        most_frequent_class, error = train_feature_value(X, y_true, feature, current_value)
        predictors[current_value] = most_frequent_class
        errors.append(error)
    total_error = sum(errors)
    return predictors, total_error

2. 构造训练数据和验证数据:数据全部来自这个Isri的数据集,这里使用train_test_split方法直接把数据分成112组训练数据和38组验证数据

from sklearn.model_selection import  train_test_split

random_state = 14

X_train, X_test, y_train, y_test = train_test_split(X_d, y, random_state=random_state)

3. 得到训练数据以后就可以开始训练:原理就是,根据不同的特征Feature循环调用Train函数,得到预测数据集,其中包含了每个feature的训练结果和error。然后根据error排序得到的最优判断方法就是我们的判断模型了。

# Compute all of the predictors
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()}
# Now choose the best and save that as "model"
# Sort by error
best_variable, best_error = sorted(errors.items(), key=itemgetter(1))[0]
print("The best model is based on variable {0} and has error {1:.2f}".format(best_variable, best_error))

# Choose the bset model
model = {'variable': best_variable,
         'predictor': all_predictors[best_variable][0]}

这里写一点简单测试代码验证一下训练结果:

4.训练结束,跑测试数据验证结果:

def predict(X_test, model):
    variable = model['variable']
    predictor = model['predictor']
    y_predicted = np.array([predictor[int(sample[variable])] for sample in X_test])
    return y_predicted

 

其实能发现一个非常明显的问题,数据被我们离散化到了0 1两个点,但是状态却又0  1  2三个,因此我们的预测数据只有两个状态,预测结果准确率受到很大的影响。

5. 评估:直接上评估结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值