游戏AI的创造思路-技术基础-决策树(1)

news2024/11/15 16:12:36

决策树,是每个游戏人必须要掌握的游戏AI构建技术,难度小,速度快,结果直观,本篇将对决策树进行小小解读~~~~

目录

1. 定义

2. 发展历史

3. 决策树的算法公式和函数

3.1. 信息增益(Information Gain)

3.2. 信息增益比(Gain Ratio) 

3.3. 基尼指数(Gini Index)

3.4. 三种划分标准对比

4. 运行原理及步骤

5. 优缺点

6. 游戏AI使用决策树算法进行NPC行为控制

6.1. 概述

6.2. 详细过程

6.3. 实例

6.4. Python实现

7. 总述


1. 定义

决策树算法是一种常用的机器学习算法,它通过递归地选择最佳特征来对数据进行分类或回归。

决策树由节点和有向边组成,内部节点表示一个特征或属性,叶节点表示分类或回归的结果。

在游戏AI中,决策树可以帮助NPC更智能地做出决策,提高游戏的趣味性和挑战性。

2. 发展历史

决策树算法的发展可以追溯到1959年,当时的研究人员试图解决人工智能中的决策问题。

1986年,乔治·卢卡斯(George A. Quinlan)提出了ID3算法,这是决策树学习的第一个主要成果。

随后,卢卡斯又提出了C4.5算法,这是ID3算法的改进版本,具有更强的鲁棒性和泛化能力。

CART(Classification and Regression Trees)算法也在此基础上发展,它可以处理连续型特征,适用于回归问题。

3. 决策树的算法公式和函数

决策树算法的核心在于如何选择最优划分特征,通常使用信息增益(Information Gain)、信息增益比(Gain Ratio)或基尼指数(Gini Index)作为划分标准。

3.1. 信息增益(Information Gain)

  • 信息增益(Information Gain)公式
    [ Gain(D, A) = Ent(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} Ent(D^v) ]
    其中,(Ent(D))是数据集D的信息熵,(D^v)是特征A上取值为v的样本子集。

  • Python 实现信息增益

import numpy as np  

def entropy(y):  
    n = len(y)  
    labels_count = {}  
    for label in y:  
        if label not in labels_count:  
            labels_count[label] = 0  
        labels_count[label] += 1  
    ent = 0.0  
    for label in labels_count:  
        p = labels_count[label] / n  
        ent -= p * np.log2(p)  
    return ent  

def info_gain(X, y, feature):  
    n = len(y)  
    ent_before = entropy(y)  
    total_gain = 0.0  
    feature_values = np.unique(X[:, feature])  
    for value in feature_values:  
        sub_X = X[X[:, feature] == value]  
        sub_y = y[X[:, feature] == value]  
        prob = len(sub_X) / n  
        total_gain += prob * entropy(sub_y)  
    return ent_before - total_gain

3.2. 信息增益比(Gain Ratio) 

决策树使用信息增益比(Gain Ratio)作为划分标准时,其公式是基于信息增益的,但增加了一个分裂信息(Split Information)的项来规范化信息增益,从而避免偏向于选择取值较多的特征。

  • 信息增益比公式
  1. 信息增益(Information Gain)
    [ Gain(D, A) = Ent(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} Ent(D^v) ]

  2. 分裂信息(Split Information)
    [ SplitInfo(D, A) = -\sum_{v=1}^{V} \frac{|D^v|}{|D|} \log_2 \frac{|D^v|}{|D|} ]

  3. 信息增益比(Gain Ratio)
    [ GainRatio(D, A) = \frac{Gain(D, A)}{SplitInfo(D, A)} ]

  • Python实现代码

以下是使用Python实现信息增益比的代码:

import numpy as np  
  
def entropy(y):  
    """计算信息熵"""  
    n = len(y)  
    labels_count = {}  
    for label in y:  
        if label not in labels_count:  
            labels_count[label] = 0  
        labels_count[label] += 1  
    ent = 0.0  
    for label in labels_count:  
        p = labels_count[label] / n  
        ent -= p * np.log2(p)  
    return ent  
  
def split_info(X, feature):  
    """计算分裂信息"""  
    n = len(X)  
    feature_values = np.unique(X[:, feature])  
    split_info = 0.0  
    for value in feature_values:  
        sub_X = X[X[:, feature] == value]  
        prob = len(sub_X) / n  
        split_info -= prob * np.log2(prob)  
    return split_info  
  
def info_gain(X, y, feature):  
    """计算信息增益"""  
    n = len(y)  
    ent_before = entropy(y)  
    total_gain = 0.0  
    feature_values = np.unique(X[:, feature])  
    for value in feature_values:  
        sub_X = X[X[:, feature] == value]  
        sub_y = y[X[:, feature] == value]  
        prob = len(sub_X) / n  
        total_gain += prob * entropy(sub_y)  
    return ent_before - total_gain  
  
def gain_ratio(X, y, feature):  
    """计算信息增益比"""  
    gain = info_gain(X, y, feature)  
    split_info = split_info(X, feature)  
    if split_info == 0:  # 避免除以0的情况  
        return 0  
    return gain / split_info  
  
# 示例数据  
X = np.array([[1, 0], [1, 1], [0, 0], [0, 1]])  
y = np.array([0, 0, 1, 1])  
  
# 计算特征0和特征1的信息增益比  
print("Gain Ratio for feature 0:", gain_ratio(X, y, 0))  
print("Gain Ratio for feature 1:", gain_ratio(X, y, 1))

这段代码定义了计算信息熵、分裂信息、信息增益和信息增益比的函数,然后在示例数据上计算了特征0和特征1的信息增益比。

3.3. 基尼指数(Gini Index)

决策树使用基尼指数(Gini index)作为划分标准时,其公式主要用于衡量数据集或数据子集的不纯度。基尼指数越小,表示数据集或数据子集的纯度越高,即选定的特征越好。

  • 基尼指数公式

对于给定的数据集 D,其基尼指数 Gini(D) 可以通过以下公式计算:

[ Gini(D) = 1 - \sum_{k=1}{J} p_k2 ]

其中,pk​ 是数据集 D 中选择第 k 类的概率,J 是类的总数。

对于特征 A,假设它有 V 个可能的取值 {a1,a2,…,aV},如果使用特征 A 对数据集 D 进行划分,可以得到 V 个子集 {D1,D2,…,DV},其中 Dv 包含所有在特征 A 上取值为 av 的样本。此时,特征 A 对数据集 D 的基尼指数 Gini(D,A)可以通过以下公式计算:

[ Gini(D, A) = \frac{\sum_{v=1}^{V} |D^v| \cdot Gini(D^v)}{|D|} ]

其中,Gini(Dv)是子集 Dv 的基尼指数,∣Dv∣ 是子集 Dv 的样本数量,∣D∣ 是数据集 D 的样本总数。

  • Python实现代码

以下是使用Python实现基尼指数的代码:

import numpy as np  
  
def gini_index(y):  
    """计算数据集的基尼指数"""  
    n = len(y)  
    labels_count = {}  
    for label in y:  
        if label not in labels_count:  
            labels_count[label] = 0  
        labels_count[label] += 1  
    gini = 1.0  
    for label in labels_count:  
        p = labels_count[label] / n  
        gini -= p**2  
    return gini  
  
def gini_index_feature(X, y, feature):  
    """计算特征对数据集的基尼指数"""  
    n = len(y)  
    feature_values = np.unique(X[:, feature])  
    total_gini = 0.0  
    for value in feature_values:  
        sub_X = X[X[:, feature] == value]  
        sub_y = y[X[:, feature] == value]  
        prob = len(sub_X) / n  
        total_gini += prob * gini_index(sub_y)  
    return total_gini  
  
# 示例数据  
X = np.array([[1, 0], [1, 1], [0, 0], [0, 1]])  
y = np.array([0, 0, 1, 1])  
  
# 计算特征0和特征1的基尼指数  
print("Gini index for feature 0:", gini_index_feature(X, y, 0))  
print("Gini index for feature 1:", gini_index_feature(X, y, 1))

这段代码定义了计算数据集基尼指数的函数 gini_index。

然后定义了计算特征对数据集基尼指数的函数 gini_index_feature

最后,在示例数据上计算了特征0和特征1的基尼指数。

3.4. 三种划分标准对比

决策树在构建过程中,选择合适的划分标准至关重要,这直接影响到决策树的性能和效率。信息增益(Information Gain)、信息增益比(Gain Ratio)和基尼指数(Gini Index)是三种常用的划分标准,它们各自具有不同的优点和缺陷。

  • 信息增益(Information Gain)

优点

  1. 直观易懂:信息增益的计算过程简单明了,易于理解和解释。它反映了使用某个特征进行划分后,数据集纯度的提升程度。
  2. 适应性强:信息增益可以适应多个类别之间的分类问题,并可以应用于离散型和连续型的特征。
  3. 多特征值偏好:信息增益在计算时考虑了特征的不确定性程度,因此对于具有更多特征值的特征更有利,这有助于捕捉数据中的细节信息。

缺陷

  1. 特征值偏好:信息增益倾向于选择具有更多特征值的特征作为划分特征,这可能导致决策树过于复杂,增加过拟合的风险。
  2. 忽略相关性:信息增益独立地计算每个特征的重要性,可能忽视了特征之间的相关性,而特征之间的相关性对于分类问题具有重要意义。
  • 信息增益比(Gain Ratio)

优点

  1. 规范化信息增益:信息增益比通过引入分裂信息(Split Information)对信息增益进行了规范化,从而减少了信息增益对具有更多特征值特征的偏好。
  2. 处理特征值偏差:在信息增益的基础上,信息增益比更好地处理了特征值分布偏差大的情况,提高了决策树的健壮性。

缺陷

  1. 计算复杂度:由于需要计算分裂信息,信息增益比的计算复杂度略高于信息增益,特别是在处理大规模数据集时。
  2. 可能偏向取值少的特征:在某些情况下,信息增益比可能过于偏向取值数目较少的特征,这需要根据具体数据集进行权衡。
  • 基尼指数(Gini Index)

优点

  1. 计算效率高:基尼指数的计算方式相对简单,不涉及对数运算,因此在处理大规模数据集时具有较高的效率。
  2. 不偏向特征值:基尼指数在计算特征重要性时不考虑特征的不确定性程度,因此不会偏向于具有更多特征值的特征。
  3. 二分类友好:基尼指数特别适用于二分类问题,能够直观地反映分类的准确性。

缺陷

  1. 不直观:基尼指数作为一个概率指标,其计算过程相对较为抽象,不如信息增益直观易懂。
  2. 多分类问题:虽然基尼指数可以应用于多分类问题,但在处理多个类别之间的分类时,其效果可能不如信息增益或信息增益比。
  • 小结

三种划分标准各有优缺点,选择哪种标准取决于具体问题的特点和数据集的特征。

在实际应用中,可以通过交叉验证等方法来评估不同划分标准对决策树性能的影响,从而选择最适合的划分标准。

4. 运行原理及步骤

决策树的构建过程包括选择最佳划分特征、递归地划分数据集、剪枝等步骤。

  • 步骤
    1. 选择最佳划分特征:根据信息增益、信息增益比或基尼指数选择最佳划分特征。
    2. 划分数据集:根据选择的特征和特征值划分数据集。
    3. 递归构建决策树:对每个子数据集重复上述步骤,直到满足停止条件(如所有样本属于同一类,或没有更多特征等)。
    4. 剪枝:为了防止过拟合,通常需要对决策树进行剪枝。
  • Python 实现决策树构建
class DecisionTree:  
    def __init__(self, max_depth=None, min_samples_split=2):  
        self.max_depth = max_depth  
        self.min_samples_split = min_samples_split  
        self.root = None  

    def fit(self, X, y):  
        self.root = self._build_tree(X, y, 0)  

    def _build_tree(self, X, y, depth):  
        # 停止条件  
        if depth >= self.max_depth or len(np.unique(y)) == 1 or len(X) < self.min_samples_split:  
            return Node(value=np.argmax(np.bincount(y)))  

        # 选择最佳划分特征  
        best_feature, best_thresh = self._best_split(X, y)  

        # 划分数据集  
        left_idxs, right_idxs = self._split(X[:, best_feature], best_thresh)  

        # 递归构建子树  
        left = self._build_tree(X[left_idxs, :], y[left_idxs], depth + 1)  
        right = self._build_tree(X[right_idxs, :], y[right_idxs], depth + 1)  

        return Node(best_feature, best_thresh, left, right)  

    # 辅助函数:选择最佳划分特征和阈值、划分数据集等

5. 优缺点

  • 优点
    • 易于理解和实现。
    • 计算效率高,对于分类问题表现良好。
    • 能够处理非线性关系。
    • 可以清晰地显示决策过程,便于解释。
  • 缺点
    • 容易过拟合,需要通过剪枝等技术解决。
    • 对缺失值比较敏感,需要额外处理。
    • 在某些复杂问题上可能不如神经网络等算法表现优异。

6. 游戏AI使用决策树算法进行NPC行为控制

在游戏开发中,NPC(非玩家角色)的行为控制是一个重要方面。

使用决策树算法可以有效地管理和控制NPC的行为,使其根据游戏环境和玩家行为做出合理的反应。

6.1. 概述

决策树是一种基于树结构的决策模型,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。

6.2. 详细过程

  1. 定义行为: 确定NPC可能执行的所有行为,例如攻击、逃跑、对话等。
  2. 确定属性: 选择影响NPC行为的属性,如玩家距离、玩家状态(攻击、防御等)、NPC当前状态等。
  3. 构建决策树: 使用属性构建决策节点,每个节点根据属性做出决策,并决定下一步的行为。
  4. 实施行为: 根据决策树的结果,NPC执行相应的行为。

6.3. 实例

假设我们有一个简单的游戏,NPC可以执行两种行为:攻击和逃跑。我们考虑两个属性:玩家距离和玩家状态。

  • 如果玩家距离小于5米且玩家处于攻击状态,NPC选择逃跑。
  • 如果玩家距离小于5米且玩家不处于攻击状态,NPC选择对话。
  • 如果玩家距离大于等于5米,NPC选择巡逻。

6.4. Python实现

class NPC:  
    def __init__(self, name):  
        self.name = name  
  
    def decide_action(self, player_distance, player_is_attacking):  
        # 根据玩家距离和玩家状态决定NPC的行为  
        if player_distance < 5:  
            if player_is_attacking:  
                return "逃跑"  
            else:  
                return "对话"  
        else:  
            return "巡逻"  
  
# 实例化NPC  
npc = NPC("守卫")  
  
# 调用decide_action方法决定NPC的行为,并打印结果  
action = npc.decide_action(3, True)  
print(f"{npc.name}决定{action}")

这段代码定义了一个NPC类,其中__init__方法是构造函数,用于初始化NPC的姓名。

decide_action方法根据传入的玩家距离(player_distance)和玩家是否处于攻击状态(player_is_attacking)来决定NPC应该执行的行为,并返回该行为。

最后,代码创建了一个名为“守卫”的NPC实例,并调用decide_action方法来决定其行为,然后打印出结果。

7. 总述

决策树算法运用于游戏的AI中,历史悠久,难度相对其他算法来说最低,也是运用最广的一种方法。简单的决策树早就在红白机时代就已初见雏形。随着近年来的发展,决策树更多的关注于自动决策树生成,后面有机会会着重于此部分论述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1910601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

枚举对象序列化规则(将Java枚举转换为JSON字符串的步骤)

文章目录 引言I 案例分析1.1 接口签名计算1.2 请求对象1.3 枚举对象序列化II 在JSON中以枚举的code值来表示枚举的实现方式2.1 自定义toString方法返回code引言 在Java中,每个对象都有一个toString方法,用于返回该对象的字符串表示。默认情况下,Enum类的toString方法返回的…

dbeaver连接postgresql报错��������: �û� “root“ Password ��֤ʧ��

文章目录 问题描述解决办法 问题描述 新安装完成的postgresql通过dbeaver连接访问报错&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;: &#xfffd;&#xfffd; “root” Password &#xfffd;&#xfffd;֤ʧ&#…

绝区柒--LLM简史

这是一系列LLM介绍的可成&#xff0c;分以下五个不分 序言&#xff1a;大型语言模型LLM简史第一部分&#xff1a;代币化——完整指南第 2 部分&#xff1a;使用 Python 中的 Scratch 从零开始使用 word2vec 进行词嵌入第 3 部分&#xff1a;用代码解释自注意力机制第 4 部分&a…

揭秘“消费即赚”的循环购模式

大家好&#xff0c;我是吴军&#xff0c;今天我将带您深入探索一种颠覆传统的新型商业模式——循环购模式。在这个模式中&#xff0c;消费者不仅能享受到购物的乐趣&#xff0c;还能通过消费获得实实在在的回报&#xff0c;甚至实现“边消费边赚钱”的奇妙体验。您是否好奇&…

Floyd算法简单理解:不断加中转点更新最短路,实现多对多最短路径

目录 Floyd算法 简单理解 简单例子 Floyd算法简单理解:不断加中转点更新最短路,实现多对多最短路径 Floyd算法 又称为Floyd-Warshall算法,是一种用于求解带权有向图中任意两顶点间的最短路径的算法。该算法利用动态规划的思想,通过不断更新顶点对之间的最短路径来实现。…

Games101——光珊化——深度缓存——shading着色 1

深度缓存 如何解决远近的问题&#xff0c;能正确的覆盖 按照画作来说&#xff0c;先画出远处的物体&#xff0c;再画出近处的物体&#xff0c;近处会将其覆盖&#xff0c;这种算法叫做画家算法 但事实上&#xff0c;排序不仅要花更多的时间&#xff0c;而且排序并不容易&…

Simulink生成代码时端口名称乱码问题

写在最前&#xff1a; 在使用Simulink生成代码时发现端口名称与模型中定义的输如输出端口名称不一致&#xff0c;代码生成的端口名称为随机字符名称。 在生成的H文件中发现&#xff0c;端口定义的结构体名称与模型中实际定义的名称不符。 模型中的定义 检查后发现&#xff0c…

Dbeaver连接人大金仓

Dbeaver 连接 人大金仓。 1、新建驱动管理器 类名&#xff1a;com.kingbase8.Driver URL模板&#xff1a;jdbc:kingbase8://{host}[:{port}]/[{database}] &#xff08;格式&#xff1a;jdbc:kingbase://IP地址:端口号/数据库名称&#xff09;&#xff1b; 默认端口&#x…

【学术会议征稿】第八届电气、机械与计算机工程国际学术会议(ICEMCE 2024)

第八届电气、机械与计算机工程国际学术会议&#xff08;ICEMCE 2024&#xff09; 2024 8th International Conference on Electrical, Mechanical and Computer Engineering 第八届电气、机械与计算机工程国际学术会议&#xff08;ICEMCE 2024&#xff09;将于2024年10月25日…

1区老牌神刊,仅37天录用!网友:“这审稿速度救了我一条命”!

关注GZH【欧亚科睿学术】&#xff0c;GET完整版2023JCR分区列表&#xff01; ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 期刊信息概况 【期刊类型】计算机科学类SCIE&EI 【出版社】ELSEVIER出版社 【期刊概况】IF&#xff1a;4.0-5.0&#xff0c;JCR1区&#xff0c;中科院3区…

MATLAB实现-基于CNN-BiLSTM卷积神经网络结合双向长短期记忆神经网络数据分类预测(多输入多分类)

MATLAB实现-基于CNN-BiLSTM卷积神经网络结合双向长短期记忆神经网络数据分类预测&#xff08;多输入多分类&#xff09; 1.数据均为Excel数据&#xff0c;直接替换数据就可以运行程序。 2.所有程序都经过验证&#xff0c;保证程序可以运行。 3.具有良好的编程习惯&#xff0…

工业机床CNC设备如何上云?

工业机床CNC设备如何上云&#xff1f; 工业机床的计算机数控&#xff08;CNC&#xff09;设备实现远程监控数据上云&#xff0c;是现代制造业智能化转型的关键一环。这一过程不仅能够实时监测设备状态、优化生产流程&#xff0c;还能通过大数据分析提升生产效率与产品质量&…

模型泛化与工程技巧-模型泛化

1. 模型存在问题 1.1 过拟合 过拟合(Overfitting):模型过于紧密或精确地匹配特定数据集,以致于无法良好地拟合其他数据或预测未来的观察结果的现象。通俗的来讲,就是训练的模型在训练集上的精确度很高,但是在测试集上的精确度却很差的现象。 1.2 如何防止过拟合—数据角度 …

汇聚荣拼多多实力怎么样?

汇聚荣拼多多实力怎么样?拼多多作为中国电子商务行业的后起之秀&#xff0c;其市场表现和商业策略引起了广泛的关注。在回答“汇聚荣拼多多实力怎么样?”这一问题时&#xff0c;我们可以明确地看到&#xff0c;拼多多通过其独特的商业模式和创新策略&#xff0c;在竞争激烈的…

1. CSS Grid 网格布局教程

CSS Grid 网格布局教程 一、概述 网格布局&#xff08;Grid&#xff09;是最强大的 CSS 布局方案。 它将网页划分成一个个网格&#xff0c;可以任意组合不同的网格&#xff0c;做出各种各样的布局。以前&#xff0c;只能通过复杂的 CSS 框架达到的效果&#xff0c;现在浏览器…

推三返一结合消费增值,高效裂变且稳定增值

在当今竞争激烈的商业版图中&#xff0c;企业正寻求创新的路径以吸引顾客、驱动增长。推三返一与消费增值模式作为两大创新策略&#xff0c;正以其独特的裂变机制&#xff0c;为企业开辟出一条通往成功的高速公路。 推三返一模式&#xff0c;其精髓在于通过消费者自身的社交网…

海外文摘杂志社《海外文摘》杂志社2024年第1期目录

作品选 封2,封3-封4 海外艺术 穿越色彩的维度康定斯基的艺术哲学 谢博文1-3 舍伍德安德森《小城畸人》中重复性女性形象塑造分析 吴燕佳 郭思霈4-6 文化艺术《海外文摘》投稿&#xff1a;cnqikantg126.com 浅谈文化润疆视域下的西域汉语诗学 蔡丽7-9 明清时期书法艺术发展 柏则…

《mysql篇》--索引事务

索引 索引的介绍 索引是帮助MySQL高效获取数据的数据结构&#xff0c;是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针&#xff0c;因为索引本身也比较大&#xff0c;所以索引一般是存储在磁盘上的&#xff0c;索引的种类有很多&#xff0c;不过如果没有特殊…

AI工具GitHub Copilot:GitHub和OpenAI联合打造的一款创新的智能代码辅助工具

GitHub Copilot是由GitHub和OpenAI联合打造的一款创新的智能代码辅助工具&#xff0c;它正改变着全球数百万开发者编写代码的方式。这个AI编程助手以其强大的代码补全和生成能力&#xff0c;帮助程序员们以更高的效率、准确性和速度完成编码任务。 喜好儿网查看更多 GitHub C…

leetcode:LCR 018. 验证回文串(python3解法)

难度&#xff1a;简单 给定一个字符串 s &#xff0c;验证 s 是否是 回文串 &#xff0c;只考虑字母和数字字符&#xff0c;可以忽略字母的大小写。 本题中&#xff0c;将空字符串定义为有效的 回文串 。 示例 1: 输入: s "A man, a plan, a canal: Panama" 输出: t…