周志华《机器学习》课后习题解析(第四章):决策树

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 周志华《机器学习》课后习题解析(第四章):决策树

4.1 试证明对于不含冲突数据(即特征向量完全相同但标记不同)的训练集,必存在与训练集一致(即训练误差为 0) 的决策树。


答:

从原书p74的图4.2的决策树学习的基本算法可以看出,生成一个叶节点有三种情况:

image.png

在这道题中,目标是找出和训练集一致的决策树,所以不必考虑第3点,从1、2情况来看出决策树中树枝停止“生长”生成叶节点只会在样本属于同一类或者所有特征值都用完的时候,那么可能导致叶节点标记与实际训练集不同时只会发生在特征值都用完的情况(同一节点中的样本,其路径上的特征值都是完全相同的),而由于训练集中没有冲突数据,那每个节点上训练误差都为0。


4.2 试析使用"最小训练误差"作为决策树划分选择准则的缺陷。


答:

这道题暂时没想出答案。在网上找了其他的答案,都是认为会造成过拟合,没给出具体证明。而我的理解决策树本身就是容易过拟合的,就算使用信息增益或者基尼指数等,依旧容易过拟合,至于使用“最小训练误差”会不会“更容易”过拟合暂时没理解明白。

待填坑。


4.3 试编程实现基于信息熵进行划分选择的决策树算法,并为表 4.3 中数据生成一棵决策树。


答:

因为数据集的原因,数据量比较小,在选择划分属性的时候会出现特征的信息增益或者信息增益率相同的情况。所有生成的决策树和书中可能不一致。并且在生成叶节点时,会出现两类数量一直的情况,这时候叶节点就随机设置一个分类了。

代码实现了以信息增益、增益率、基尼指数划分准则。下面一道题(4.4)也是用相同的代码。另外画图的代码是主要参考《机器学习实战》决策树那一章画图源码。

有些地方代码有点乱,比如进行剪枝的部分就有大量重复代码;并且预剪枝部分可以在生成决策树的时候实现,减少计算量。以后有机会再优化一下。

代码在:

https://github.com/han1057578619/MachineLearning_Zhouzhihua_ProblemSets/tree/master/ch4--%E5%86%B3%E7%AD%96%E6%A0%91/4.3-4.4

pruning.py

import pandas as pd
import numpy as np
def post_pruning(X_train, y_train, X_val, y_val, tree_=None):
    if tree_.is_leaf:
        return tree_
    if X_val.empty:         # 验证集为空集时,不再剪枝
        return tree_
    most_common_in_train = pd.value_counts(y_train).index[0]
    current_accuracy = np.mean(y_val == most_common_in_train)  # 当前节点下验证集样本准确率
    if tree_.is_continuous:
        up_part_train = X_train.loc[:, tree_.feature_name] >= tree_.split_value
        down_part_train = X_train.loc[:, tree_.feature_name] < tree_.split_value
        up_part_val = X_val.loc[:, tree_.feature_name] >= tree_.split_value
        down_part_val = X_val.loc[:, tree_.feature_name] < tree_.split_value
        up_subtree = post_pruning(X_train[up_part_train], y_train[up_part_train], X_val[up_part_val],
                                  y_val[up_part_val],
                                  tree_.subtree['>= {:.3f}'.format(tree_.split_value)])
        tree_.subtree['>= {:.3f}'.format(tree_.split_value)] = up_subtree
        down_subtree = post_pruning(X_train[down_part_train], y_train[down_part_train],
                                    X_val[down_part_val], y_val[down_part_val],
                                    tree_.subtree['< {:.3f}'.format(tree_.split_value)])
        tree_.subtree['< {:.3f}'.format(tree_.split_value)] = down_subtree
        tree_.high = max(up_subtree.high, down_subtree.high) + 1
        tree_.leaf_num = (up_subtree.leaf_num + down_subtree.leaf_num)
        if up_subtree.is_leaf and down_subtree.is_leaf:
            def split_fun(x):
                if x >= tree_.split_value:
                    return '>= {:.3f}'.format(tree_.split_value)
                else:
                    return '< {:.3f}'.format(tree_.split_value)
            val_split = X_val.loc[:, tree_.feature_name].map(split_fun)
            right_class_in_val = y_val.groupby(val_split).apply(
                lambda x: np.sum(x == tree_.subtree[x.name].leaf_class))
            split_accuracy = right_class_in_val.sum() / y_val.shape[0]
            if current_accuracy > split_accuracy:  # 若当前节点为叶节点时的准确率大于不剪枝的准确率,则进行剪枝操作——将当前节点设为叶节点
                set_leaf(pd.value_counts(y_train).index[0], tree_)
    else:
        max_high = -1
        tree_.leaf_num = 0
        is_all_leaf = True  # 判断当前节点下,所有子树是否都为叶节点
        for key in tree_.subtree.keys():
            this_part_train = X_train.loc[:, tree_.feature_name] == key
            this_part_val = X_val.loc[:, tree_.feature_name] == key
            tree_.subtree[key] = post_pruning(X_train[this_part_train], y_train[this_part_train],
                                              X_val[this_part_val], y_val[this_part_val], tree_.subtree[key])
            if tree_.subtree[key].high > max_high:
                max_high = tree_.subtree[key].high
            tree_.leaf_num += tree_.subtree[key].leaf_num
            if not tree_.subtree[key].is_leaf:
                is_all_leaf = False
        tree_.high = max_high + 1
        if is_all_leaf:  # 若所有子节点都为叶节点,则考虑是否进行剪枝
            right_class_in_val = y_val.groupby(X_val.loc[:, tree_.feature_name]).apply(
                lambda x: np.sum(x == tree_.subtree[x.name].leaf_class))
            split_accuracy = right_class_in_val.sum() / y_val.shape[0]
            if current_accuracy > split_accuracy:  # 若当前节点为叶节点时的准确率大于不剪枝的准确率,则进行剪枝操作——将当前节点设为叶节点
                set_leaf(pd.value_counts(y_train).index[0], tree_)
    return tree_
def pre_pruning(X_train, y_train, X_val, y_val, tree_=None):
    if tree_.is_leaf:  # 若当前节点已经为叶节点,那么就直接return了
        return tree_
    if X_val.empty: # 验证集为空集时,不再剪枝
        return tree_
    # 在计算准确率时,由于西瓜数据集的原因,好瓜和坏瓜的数量会一样,这个时候选择训练集中样本最多的类别时会不稳定(因为都是50%),
    # 导致准确率不稳定,当然在数量大的时候这种情况很少会发生。
    most_common_in_train = pd.value_counts(y_train).index[0]
    current_accuracy = np.mean(y_val == most_common_in_train)
    if tree_.is_continuous:  # 连续值时,需要将样本分割为两部分,来计算分割后的正确率
        split_accuracy = val_accuracy_after_split(X_train[tree_.feature_name], y_train,
                                                  X_val[tree_.feature_name], y_val,
                                                  split_value=tree_.split_value)
        if current_accuracy >= split_accuracy:  # 当前节点为叶节点时准确率大于或分割后的准确率时,选择不划分
            set_leaf(pd.value_counts(y_train).index[0], tree_)
        else:
            up_part_train = X_train.loc[:, tree_.feature_name] >= tree_.split_value
            down_part_train = X_train.loc[:, tree_.feature_name] < tree_.split_value
            up_part_val = X_val.loc[:, tree_.feature_name] >= tree_.split_value
            down_part_val = X_val.loc[:, tree_.feature_name] < tree_.split_value
            up_subtree = pre_pruning(X_train[up_part_train], y_train[up_part_train], X_val[up_part_val],
                                     y_val[up_part_val],
                                     tree_.subtree['>= {:.3f}'.format(tree_.split_value)])
            tree_.subtree['>= {:.3f}'.format(tree_.split_value)] = up_subtree
            down_subtree = pre_pruning(X_train[down_part_train], y_train[down_part_train],
                                       X_val[down_part_val],
                                       y_val[down_part_val],
                                       tree_.subtree['< {:.3f}'.format(tree_.split_value)])
            tree_.subtree['< {:.3f}'.format(tree_.split_value)] = down_subtree
            tree_.high = max(up_subtree.high, down_subtree.high) + 1
            tree_.leaf_num = (up_subtree.leaf_num + down_subtree.leaf_num)
    else:  # 若是离散值,则变量所有值,计算分割后正确率
        split_accuracy = val_accuracy_after_split(X_train[tree_.feature_name], y_train,
                                                  X_val[tree_.feature_name], y_val)
        if current_accuracy >= split_accuracy:
            set_leaf(pd.value_counts(y_train).index[0], tree_)
        else:
            max_high = -1
            tree_.leaf_num = 0
            for key in tree_.subtree.keys():
                this_part_train = X_train.loc[:, tree_.feature_name] == key
                this_part_val = X_val.loc[:, tree_.feature_name] == key
                tree_.subtree[key] = pre_pruning(X_train[this_part_train], y_train[this_part_train],
                                                 X_val[this_part_val],
                                                 y_val[this_part_val], tree_.subtree[key])
                if tree_.subtree[key].high > max_high:
                    max_high = tree_.subtree[key].high
                tree_.leaf_num += tree_.subtree[key].leaf_num
            tree_.high = max_high + 1
    return tree_
def set_leaf(leaf_class, tree_):
    # 设置节点为叶节点
    tree_.is_leaf = True  # 若划分前正确率大于划分后正确率。则选择不划分,将当前节点设置为叶节点
    tree_.leaf_class = leaf_class
    tree_.feature_name = None
    tree_.feature_index = None
    tree_.subtree = {}
    tree_.impurity = None
    tree_.split_value = None
    tree_.high = 0  # 重新设立高 和叶节点数量
    tree_.leaf_num = 1
def val_accuracy_after_split(feature_train, y_train, feature_val, y_val, split_value=None):
    # 若是连续值时,需要需要按切分点对feature 进行分组,若是离散值,则不用处理
    if split_value is not None:
        def split_fun(x):
            if x >= split_value:
                return '>= {:.3f}'.format(split_value)
            else:
                return '< {:.3f}'.format(split_value)
        train_split = feature_train.map(split_fun)
        val_split = feature_val.map(split_fun)
    else:
        train_split = feature_train
        val_split = feature_val
    majority_class_in_train = y_train.groupby(train_split).apply(
        lambda x: pd.value_counts(x).index[0])  # 计算各特征下样本最多的类别
    right_class_in_val = y_val.groupby(val_split).apply(
        lambda x: np.sum(x == majority_class_in_train[x.name]))  # 计算各类别对应的数量
    return right_class_in_val.sum() / y_val.shape[0]  # 返回准确率

image.png


4.4 试编程实现基于基尼指数进行划分选择的决策树算法,为表 4.2 中数据生成预剪枝、后剪枝决策树并与未剪枝决策树进行比较.


答:

https://github.com/han1057578619/MachineLearning_Zhouzhihua_ProblemSets/tree/master/ch4--%E5%86%B3%E7%AD%96%E6%A0%91/4.3-4.4

未剪枝、后剪枝、预剪枝生成决策树分别如下,总体来说后剪枝会相比于预剪枝保留更多的分支。

有两个需要注意的地方。一个是在4.3中说过的,因为划分属性的信息增益或者基尼指数相同的原因,这个时候选择哪一个属性作为划分属性都是对的,生成决策树和书中不一致是正常的(书中第一个节点为“脐部”)。另外数据量这么小的情况下,常常会出现剪枝前后准确率不变的情况,原书中也提到这种情况通常要进行剪枝的,但是这道题中若进行剪枝,会出现只有一个叶节点的情况。为了画图好看点...所以都不无论在预剪枝还是后剪枝中,这种情况都会采取不剪枝策略。参考原书P82。

经过测试,在未剪枝的情况下,验证集上准确率为0.2857;后剪枝准确率为0.5714;预剪枝也为0.5714。

image.png

未剪枝

image.png

后剪枝

image.png

预剪枝


4. 5 试编程实现基于对率回归进行划分选择的决策树算法,并为表 4.3 中数据生成一棵决策树.


答:

这个没实现。一种思路就是拟合对率回归后,从所有特征中选择一个 image.png 值最高的一个特征值,即权重最高的一个特征值作为划分选择,但是没想好对于One-hot之后的特征权重怎么计算,比如“色泽”有三种取值“乌黑”、“青绿”、“浅白”,在One-hot之后会有三个特征,那么最后“色泽”这个特征的权重应该是取平均值?以后有机会....也不填坑。


4.6 试选择 4 个 UCI 数据集,对上述 3 种算法所产生的未剪枝、预剪枝、后剪枝决策树进行实验比较,并进行适当的统计显著性检验.


答:

只拿sklearn中自带的iris数据集试了一下剪枝后的准确率,发现不同随机数种子(使得数据集划分不同)导致最后验证集的准确率变化挺大。

统计显著性检验没实现。

https://github.com/han1057578619/MachineLearning_Zhouzhihua_ProblemSets/tree/master/ch4--%E5%86%B3%E7%AD%96%E6%A0%91/4.6

'''
treeCreater 和 treePlotter 代码见 ch4/4.3-4.4
数据量不大,不同的随机数种子,测试集的准确率变化较大
'''
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
import numpy as np
import treeCreater
import treePlottter
iris = datasets.load_iris()
X = pd.DataFrame(iris['data'], columns=iris['feature_names'])
y = pd.Series(iris['target_names'][iris['target']])
# 取三个样本为测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=15)
# 剩下120个样本中,取30个作为剪枝时的验证集
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=15)
# 不剪枝
tree_no_pruning = treeCreater.DecisionTree('gini')
tree_no_pruning.fit(X_train, y_train, X_val, y_val)
print('不剪枝:', np.mean(tree_no_pruning.predict(X_test) == y_test))
# treePlottter.create_plot(tree_no_pruning.tree_)
# 预剪枝
tree_pre_pruning = treeCreater.DecisionTree('gini', 'pre_pruning')
tree_pre_pruning.fit(X_train, y_train, X_val, y_val)
print('预剪枝:', np.mean(tree_pre_pruning.predict(X_test) == y_test))
# treePlottter.create_plot(tree_pre_pruning.tree_)
# 后剪枝
tree_post_pruning = treeCreater.DecisionTree('gini', 'post_pruning')
tree_post_pruning.fit(X_train, y_train, X_val, y_val)
print('后剪枝:', np.mean(tree_post_pruning.predict(X_test) == y_test))
# treePlottter.create_plot(tree_post_pruning.tree_)


4.7 图 4.2 是一个递归算法,若面临巨量数据,则决策树的层数会很深,使用递归方法易导致"栈"溢出。试使用"队列"数据结构,以参数MaxDepth 控制树的最大深度,写出与图 4.2 等价、但不使用递归的决策树生成算法.


答:

主要思路每一次循环遍历一层下节点(除去叶节点),为每一个节点生成子节点,将非叶节点入队;用参数L保存每一层有多少个节点。下一次循环执行同样的步骤。直至所有的节点都叶节点,此时队列为空。具体如下:

输入:训练集D = {(x1, y1), (x2, y2)...(xm, ym)};
    属性集A = {a1, a2... ad};
    最大深度MaxDepth = maxDepth
过程:函数TreeDenerate(D, A, maxDepth)
生成三个队列,NodeQueue、DataQueue、AQueue分别保存节点、数据、和剩余属性集;
2生成节点Node_root;
3:  if A为空 OR D上样本都为同一类别:
4:    将Node_root标记为叶节点,其标记类别为D中样本最多的类;
5:     return Node_root;
6:  end if 
7:  将Node入队NodeQueue; 将D入队 DataQueue; 将A入队AQueue;
8:  初始化深度depth=0;
9:  初始化L = 1;  # L用于记录每一层有多少非叶节点。
10: while NodeQueue 非空:
11:    L* = 0
12:    for _ in range(L):      # 遍历当前L个非叶节点
13:      NodeQueue 出队Node; DataQueue出队D; AQueue 出队A;
14:      从A中选择一个最优划分属性a*;
15:      for a* 的每一个值 a*v do:
16:        新建一个node*,并将node*连接为Node的一个分支;
17:        令 Dv表示为D中在a*上取值为a*v的样本子集;
18:        if Dv为空:
19:          将node*标记为叶节点,其标记类别为D中样本最多的类;
20:          continue;
21:        end if
22:        if A\{a*}为空 OR Dv上样本都为同一类别 OR depth == maxDepth:
23:          将node*标记为叶节点,其标记类别为Dv中样本最多的类;
24:          continue;
25:        end if       
26:        将node*入队NodeQueue; 将Dv入队 DataQueue; 将A\{a*} 入队AQueue;
27:        L* += 1;    # 用于计算在第depth+1 层有多少个非叶节点
28:    L = L*;
29:    depth += 1;
30:  return Node_root;
输入以Node_root为根节点的一颗决策树


4.8 试将决策树生成的深度优先搜索过程修改为广度优先搜索,以参数MaxNode控制树的最大结点数,将题 4.7 中基于队列的决策树算法进行改写。对比题 4.7 中的算法,试析哪种方式更易于控制决策树所需存储不超出内存。


答:

4.7写的算法就是广度优先搜索的。这道题将MaxNode改为MaxDepth,只需要改几个地方。有一点需要注意的地方,就是在给一个节点生成子节点时(19-32行),可能造成节点数大于最大值的情况,比如某属性下有3种取值,那么至少要生成3个叶节点,这个时候节点总数可能会超过最大值,这时最终节点数可能会是MaxNode+2。

至于两种算法对比。个人理解当数据特征值,各属性的取值较多时,形成的决策树会趋于较宽类型的树,这时使用广度优先搜索更容易控制内存。若属性取值较少时,深度优先搜索更容易控制内存。

对4.7中修改如下:

输入:训练集D = {(x1, y1), (x2, y2)...(xm, ym)};
    属性集A = {a1, a2... ad};
    最大深度MaxNode = maxNode
过程:函数TreeDenerate(D, A, maxNode)
1:  生成三个队列,NodeQueue、DataQueue、AQueue分别保存节点、数据、和剩余属性集;
2:  生成节点Node_root;
3:  if A为空 OR D上样本都为同一类别:
4:    将Node_root标记为叶节点,其标记类别为D中样本最多的类;
5:     return Node_root;
6:  end if 
7:  将Node入队NodeQueue; 将D入队 DataQueue; 将A入队AQueue;
8:  初始化深度numNode=1;
9:  初始化L = 1;  # L用于记录每一层有多少非叶节点。
10: while NodeQueue 非空:
11:    L* = 0
12:    for _ in range(L):      # 遍历当前L个非叶节点
13:      NodeQueue 出队Node; DataQueue出队D; AQueue 出队A;
14:      if numNode >= maxNode:
15:        将Node标记为叶节点,其标记类别为D中样本最多的类;
16:        continue;
17:      end if;
18:      从A中选择一个最优划分属性a*;
19:      for a* 的每一个值 a*v do:
20:        numNode+=1
21:        生成一个node*,并将node*连接为Node的一个分支;
22:        令 Dv表示为D中在a*上取值为a*v的样本子集;
23:        if Dv为空:
24:          将node*标记为叶节点,其标记类别为D中样本最多的类;
25:          continue;
26:        end if
27:        if A\{a*}为空 OR Dv上样本都为同一类别:
28:          将node*标记为叶节点,其标记类别为Dv中样本最多的类;
29:          continue;
30:        end if       
31:        将node*入队NodeQueue; 将Dv入队 DataQueue; 将A\{a*} 入队AQueue;
32:        L* += 1;    # 用于计算在第depth+1 层有多少个非叶节点
33:      end if;
34:    L = L*;
35:  return Node_root;

image.png


4.10 从网上下载或自己编程实现任意一种多变量决策树算法,并观察其在西瓜数据集 3.0 上产生的结果


答:

待补充。


相关文章
|
3月前
|
机器学习/深度学习 存储 算法
决策树和随机森林在机器学习中的应用
在机器学习领域,决策树(Decision Tree)和随机森林(Random Forest)是两种非常流行且强大的分类和回归算法。它们通过模拟人类决策过程,将复杂的数据集分割成易于理解和处理的子集,从而实现对新数据的准确预测。
107 10
|
3月前
|
机器学习/深度学习 数据采集 算法
R语言中的机器学习库:caret与mlr的深度解析
【9月更文挑战第2天】Caret和mlr是R语言中两个非常重要的机器学习库,它们在数据预处理、模型构建、调优和评估等方面提供了丰富的功能。Caret以其易用性和集成性著称,适合初学者和快速原型开发;而mlr则以其全面性和可扩展性见长,适合处理复杂的机器学习项目。在实际应用中,用户可以根据具体需求和项目特点选择合适的库进行开发。无论是学术研究、商业智能还是教育场景,这两个库都能为数据科学家和机器学习爱好者提供强大的支持。
|
2月前
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
84 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
2月前
|
机器学习/深度学习 算法 Python
深度解析机器学习中过拟合与欠拟合现象:理解模型偏差背后的原因及其解决方案,附带Python示例代码助你轻松掌握平衡技巧
【10月更文挑战第10天】机器学习模型旨在从数据中学习规律并预测新数据。训练过程中常遇过拟合和欠拟合问题。过拟合指模型在训练集上表现优异但泛化能力差,欠拟合则指模型未能充分学习数据规律,两者均影响模型效果。解决方法包括正则化、增加训练数据和特征选择等。示例代码展示了如何使用Python和Scikit-learn进行线性回归建模,并观察不同情况下的表现。
346 3
|
2月前
|
机器学习/深度学习 人工智能 算法
揭开深度学习与传统机器学习的神秘面纱:从理论差异到实战代码详解两者间的选择与应用策略全面解析
【10月更文挑战第10天】本文探讨了深度学习与传统机器学习的区别,通过图像识别和语音处理等领域的应用案例,展示了深度学习在自动特征学习和处理大规模数据方面的优势。文中还提供了一个Python代码示例,使用TensorFlow构建多层感知器(MLP)并与Scikit-learn中的逻辑回归模型进行对比,进一步说明了两者的不同特点。
74 2
|
3月前
|
机器学习/深度学习 数据采集 监控
探索机器学习:从数据到决策
【9月更文挑战第18天】在这篇文章中,我们将一起踏上一段激动人心的旅程,穿越机器学习的世界。我们将探讨如何通过收集和处理数据,利用算法的力量来预测未来的趋势,并做出更加明智的决策。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和思考方式。
|
3月前
|
机器学习/深度学习 算法 Python
从菜鸟到大师:一棵决策树如何引领你的Python机器学习之旅
【9月更文挑战第9天】在数据科学领域,机器学习如同璀璨明珠,吸引无数探索者。尤其对于新手而言,纷繁复杂的算法常让人感到迷茫。本文将以决策树为切入点,带您从Python机器学习的新手逐步成长为高手。决策树以其直观易懂的特点成为入门利器。通过构建决策树分类器并应用到鸢尾花数据集上,我们展示了其基本用法及效果。掌握决策树后,还需深入理解其工作原理,调整参数,并探索集成学习方法,最终将所学应用于实际问题解决中,不断提升技能。愿这棵智慧之树助您成为独当一面的大师。
47 3
|
3月前
|
机器学习/深度学习 算法 Python
决策树下的智慧果实:Python机器学习实战,轻松摘取数据洞察的果实
【9月更文挑战第7天】当我们身处数据海洋,如何提炼出有价值的洞察?决策树作为一种直观且强大的机器学习算法,宛如智慧之树,引领我们在繁复的数据中找到答案。通过Python的scikit-learn库,我们可以轻松实现决策树模型,对数据进行分类或回归分析。本教程将带领大家从零开始,通过实际案例掌握决策树的原理与应用,探索数据中的秘密。
50 1
|
3月前
|
机器学习/深度学习 数据采集 存储
一文读懂蒙特卡洛算法:从概率模拟到机器学习模型优化的全方位解析
蒙特卡洛方法起源于1945年科学家斯坦尼斯劳·乌拉姆对纸牌游戏中概率问题的思考,与约翰·冯·诺依曼共同奠定了该方法的理论基础。该方法通过模拟大量随机场景来近似复杂问题的解,因命名灵感源自蒙特卡洛赌场。如今,蒙特卡洛方法广泛应用于机器学习领域,尤其在超参数调优、贝叶斯滤波等方面表现出色。通过随机采样超参数空间,蒙特卡洛方法能够高效地找到优质组合,适用于处理高维度、非线性问题。本文通过实例展示了蒙特卡洛方法在估算圆周率π和优化机器学习模型中的应用,并对比了其与网格搜索方法的性能。
321 1
|
4月前
|
图形学 机器学习/深度学习 人工智能
颠覆传统游戏开发,解锁未来娱乐新纪元:深度解析如何运用Unity引擎结合机器学习技术,打造具备自我进化能力的智能游戏角色,彻底改变你的游戏体验——从基础设置到高级应用全面指南
【8月更文挑战第31天】本文探讨了如何在Unity中利用机器学习增强游戏智能。作为领先的游戏开发引擎,Unity通过ML-Agents Toolkit等工具支持AI代理的强化学习训练,使游戏角色能自主学习完成任务。文章提供了一个迷宫游戏示例及其C#脚本,展示了环境观察、动作响应及奖励机制的设计,并介绍了如何设置训练流程。此外,还提到了Unity与其他机器学习框架(如TensorFlow和PyTorch)的集成,以实现更复杂的游戏玩法。通过这些技术,游戏的智能化程度得以显著提升,为玩家带来更丰富的体验。
65 1

热门文章

最新文章

推荐镜像

更多