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

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

目录

[1. 定义](#1. 定义)

[2. 发展历史](#2. 发展历史)

[3. 决策树的算法公式和函数](#3. 决策树的算法公式和函数)

[3.1. 信息增益(Information Gain)](#3.1. 信息增益(Information Gain))

[3.2. 信息增益比(Gain Ratio)](#3.2. 信息增益比(Gain Ratio))

[3.3. 基尼指数(Gini Index)](#3.3. 基尼指数(Gini Index))

[3.4. 三种划分标准对比](#3.4. 三种划分标准对比)

[4. 运行原理及步骤](#4. 运行原理及步骤)

[5. 优缺点](#5. 优缺点)

[6. 游戏AI使用决策树算法进行NPC行为控制](#6. 游戏AI使用决策树算法进行NPC行为控制)

[6.1. 概述](#6.1. 概述)

[6.2. 详细过程](#6.2. 详细过程)

[6.3. 实例](#6.3. 实例)

[6.4. Python实现](#6.4. Python实现)

[7. 总述](#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)公式

    其中,是数据集的信息熵,是特征上取值为的样本子集。

  • 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 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)

  2. 分裂信息(Split Information)

  3. 信息增益比(Gain Ratio)

  • Python实现代码

以下是使用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) 可以通过以下公式计算:

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

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

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

  • Python实现代码

以下是使用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 实现决策树构建
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实现

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

相关推荐
云起无垠2 分钟前
第74期 | GPTSecurity周报
人工智能·安全·网络安全
workflower11 分钟前
AI+自动驾驶
人工智能·机器学习·自动驾驶
爱技术的小伙子21 分钟前
【ChatGPT】 让ChatGPT模拟客户服务对话与应答策略
人工智能·chatgpt
OptimaAI1 小时前
【 LLM论文日更|检索增强:大型语言模型是强大的零样本检索器 】
人工智能·深度学习·语言模型·自然语言处理·nlp
谢眠1 小时前
机器学习day4-朴素贝叶斯分类和决策树
人工智能·机器学习
HelpHelp同学1 小时前
教育机构内部知识库:教学资源的集中管理与优化
人工智能·知识库软件·搭建知识库·知识管理工具
深度学习lover1 小时前
<项目代码>YOLOv8 番茄识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·番茄识别
IT古董1 小时前
【机器学习】机器学习中用到的高等数学知识-1.线性代数 (Linear Algebra)
人工智能·python·线性代数·机器学习
baijin_cha1 小时前
机器学习基础04_朴素贝叶斯分类&决策树分类
笔记·决策树·机器学习·分类
飞腾开发者1 小时前
飞腾平台Arm NN软件栈安装使用指南
linux·运维·人工智能·机器学习·计算机视觉