2018-07-05

数据挖掘实验报告

实验要求:

对样本进行二分类,获取分类概率

采用方法:

随机森林

方法简介

随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。随机森林方法要求我们训练n棵决策树,
其中每棵决策树仅随机选取一部分样本和一部分特征进行训练。对于分类问题,每棵决策树都是一个分类器,那么对于一个输入样本,N棵树会有N个分类结果。随机森林集成了所有的分类投票结果,将投票次数最多的类别指定为最终的输出。

决策树实现

采用贪心的策略,获取每轮迭代的局部最优解

  1. 获取最佳分割
    遍历当前节点的训练样本的每一个特征f:
    对当前样本的f特征列进行排序
    根据排序结果,遍历特征分割点t
    计算根据f特征,t分割点的impurity(可采用gini index 或者 信息增益)
    获得min_impurity,min_impurity对应的分割就是当前最佳分割
for feature_i in range(n_features):
    # All values of feature_i
    feature_values = X[:, feature_i]

    # 预排序
    feature_values = sorted(enumerate(feature_values), key=lambda x:x[1])

    # 树的左儿子的类别统计
    X1typeNum = np.zeros(len(typeNum))
    # 树的右儿子的类别统计
    X2typeNum = copy.deepcopy(typeNum)

    feature_values_i = 0

    while feature_values_i < n_samples:
        threshold = feature_values[feature_values_i][1]
        while feature_values_i < n_samples and feature_values[feature_values_i][1] == threshold:
            X1typeNum[y[feature_values[feature_values_i][0]][0]] += 1
            X2typeNum[y[feature_values[feature_values_i][0]][0]] -= 1
            feature_values_i += 1

        X1gini = self._impurity_calculation(X1typeNum)
        X2gini = self._impurity_calculation(X2typeNum)
        Rgini = (feature_values_i/n_samples)*X1gini+(1-feature_values_i/n_samples)*X2gini


        if Rgini < minRgini:
            minRgini = Rgini
            best_criteria = {"feature_i": feature_i, "threshold": threshold}
            best_feature_values_i = feature_values_i


    if best_criteria["feature_i"] == feature_i:
        X1array = [e[0] for e in feature_values[:best_feature_values_i]]
        X1array = sorted(X1array)
        # print("X1araay:",X1array)
        X1 = X[X1array,:]
        y1 = y[X1array,:]
        X2 = np.delete(X,X1array,axis=0)
        y2 = np.delete(y,X1array,axis=0)
        best_sets = {
            "leftX": X1,  # X of left subtree
            "lefty": y1,  # y of left subtree
            "rightX": X2,  # X of right subtree
            "righty": y2  # y of right subtree
        }

2.停止条件

  1. 树深达到设定的最大深度
  2. 分割无法获得更小的impurity
  3. 节点已不可分割

3.节点构建
叶子节点:
value: 分类lable

非叶子节点:
feature_i: 选择的分割特征
threshold:对应的分割值
true_branch: 小于等于分割值,走这个分支
false_branch: 大于分割值,走这个分支

class DecisionNode():
    """Class that represents a decision node or leaf in the decision tree

    Parameters:
    -----------
    feature_i: int
        Feature index which we want to use as the threshold measure.
    threshold: float
        The value that we will compare feature values at feature_i against to
        determine the prediction.
    value: 
        The class prediction if classification tree, or float value if regression tree.
    true_branch: DecisionNode
        Next decision node for samples where features value met the threshold.
    false_branch: DecisionNode
        Next decision node for samples where features value did not meet the threshold.
    """

    def __init__(self, feature_i=None, threshold=None,
                 value=None, true_branch=None, false_branch=None):
        self.feature_i = feature_i  # Index for the feature that is tested
        self.threshold = threshold  # Threshold value for feature
        self.value = value  # Value if the node is a leaf in the tree
        self.true_branch = true_branch  # 'Left' subtree
        self.false_branch = false_branch  # 'Right' subtree

并行化的实现

采用python多进程的方法
(由于python多线程只能使用一个核,对CPU密集型的程序,才用多进程更为合适)

随机森林的并行比较简单,要建100棵树的森林,仅需将任务平均分配给各个进程即可

使用Multiprocessing.Pool

    pool = Pool(processes=4)
    result = []

    processesNum = 4

    n_estimators = 100

    for i in range(processesNum):
        msg = "hello %d" %(i)
        # 异步进程
        result.append(pool.apply_async(doRF,(X_train,y_train,
                X_test,int(n_estimators/processesNum), )))
    pool.close()
    pool.join()

    a = []
    for res in result:
        a.append(res.get())

对比

训练样本数 n_estimators 无并行耗时 4进程耗时 2进程耗时
20000 100 80.5810 43.1366 58.0753
100000 100 426.3829 247.0801 285.9107

显然在速度上有很大提升

Cache友好

获取最佳分割时,先对特征的分割值进行预排序,遍历排序后的分割值,计算基尼指数或熵时,可以不用每次都去遍历整个样本,极大的减少了读取内存的开销。

举例:
对于这样一个样本

feature label
1 0
6 1
0 1
5 0

没有进行预排序时,我们遍历分割值t = 1,6,0,5,每次都需要扫描整个样本,判断每一行的feature<=t 的结果,再查看对应label,一共需要遍历4次样本

预排后,我们遍历t=0,1,5,6,知道对应index=2,0,3,1

 feature_values = sorted(enumerate(feature_values), key=lambda x:x[1])

先假设左子树节点=NULL, 右子树节点=当前节点,知道了现在两边的label分布情况 left: 0:0, 1:0 right: 0:2, 1:2
t = 0: 查询index=2的feature 发现=t,将index=2的节点划分给左子树,记录其label信息 left: 0:0, 1:1 right: 0:2, 1:1
查询index=0的feature 发现>t,over, t=0分割完毕 通过label分布计算基尼指数
t = 1: 查询index = 0的feature 发现 = t,重复上述操作
...
如此我们只需遍历一次样本即可对一个特征的所有分割值进行处理,找出最佳分割值

实现细节

  1. 在每次计算基尼指数时,无需做真正的”分割“,即不用真的把样本按该特征及该分割值进行分割再进行计算,原因是我们做了预排序,可以维护两个类之间一进一出的关系,减少读写内存时间。只有在确定最佳分割后才进行分割。

实验截图

4进程10w数据
2进程10w数据
不并行10w数据
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容