PHP 简单决策树怎么弄

wen PHP项目 3

本文目录导读:

PHP 简单决策树怎么弄

  1. 方法一:使用数组结构(最简单)
  2. 方法二:面向对象方式
  3. 方法三:关联数组的递归查找
  4. 方法四:更完整的实现(含ID3算法简化版)
  5. 推荐选择

我来给你介绍几种PHP实现简单决策树的方法:

使用数组结构(最简单)

<?php
// 基于数组的简单决策树
function decisionTree($data) {
    // 决策规则
    $rules = [
        'age' => [
            'young' => [
                'student' => 'yes',
                'not_student' => 'no'
            ],
            'middle' => 'yes',
            'old' => [
                'credit' => [
                    'excellent' => 'yes',
                    'fair' => 'no'
                ]
            ]
        ]
    ];
    // 实际决策
    if ($data['age'] === 'young') {
        if ($data['student'] === true) {
            return 'yes';
        } else {
            return 'no';
        }
    } elseif ($data['age'] === 'middle') {
        return 'yes';
    } elseif ($data['age'] === 'old') {
        if ($data['credit'] === 'excellent') {
            return 'yes';
        } else {
            return 'no';
        }
    }
    return 'unknown';
}
// 使用示例
$data = ['age' => 'young', 'student' => true];
echo decisionTree($data); // 输出: yes
?>

面向对象方式

<?php
class DecisionNode {
    public $attribute;
    public $children = [];
    public $decision;
    public function __construct($attribute = null, $decision = null) {
        $this->attribute = $attribute;
        $this->decision = $decision;
    }
    public function addChild($value, $node) {
        $this->children[$value] = $node;
    }
    public function predict($data) {
        if ($this->decision !== null) {
            return $this->decision;
        }
        $value = $data[$this->attribute] ?? null;
        if ($value !== null && isset($this->children[$value])) {
            return $this->children[$value]->predict($data);
        }
        return 'unknown';
    }
}
class DecisionTree {
    private $root;
    public function build($samples, $features) {
        $this->root = $this->buildTree($samples, $features);
    }
    private function buildTree($samples, $features) {
        // 如果所有样本分类相同
        $classes = array_column($samples, 'label');
        if (count(array_unique($classes)) === 1) {
            return new DecisionNode(null, $classes[0]);
        }
        // 如果没有特征可用
        if (empty($features)) {
            $counts = array_count_values($classes);
            $mostCommon = array_search(max($counts), $counts);
            return new DecisionNode(null, $mostCommon);
        }
        // 选择最优特征(这里简化为第一个特征)
        $bestFeature = array_shift($features);
        $root = new DecisionNode($bestFeature);
        // 根据特征值分割数据
        $groups = [];
        foreach ($samples as $sample) {
            $value = $sample[$bestFeature];
            $groups[$value][] = $sample;
        }
        // 递归构建子树
        foreach ($groups as $value => $group) {
            $child = $this->buildTree($group, $features);
            $root->addChild($value, $child);
        }
        return $root;
    }
    public function predict($data) {
        return $this->root->predict($data);
    }
}
// 使用示例
$samples = [
    ['age' => 'young', 'income' => 'high', 'label' => 'yes'],
    ['age' => 'young', 'income' => 'low', 'label' => 'no'],
    ['age' => 'middle', 'income' => 'high', 'label' => 'yes'],
    ['age' => 'old', 'income' => 'low', 'label' => 'no'],
];
$tree = new DecisionTree();
$tree->build($samples, ['age', 'income']);
$prediction = $tree->predict(['age' => 'young', 'income' => 'high']);
echo "预测结果: " . $prediction; // 输出: yes
?>

关联数组的递归查找

<?php
class SimpleDecisionTree {
    private $tree;
    public function __construct() {
        // 构建决策树结构
        $this->tree = [
            'weather' => [
                'sunny' => [
                    'humidity' => [
                        'high' => 'no',
                        'normal' => 'yes'
                    ]
                ],
                'rainy' => [
                    'wind' => [
                        'strong' => 'no',
                        'weak' => 'yes'
                    ]
                ],
                'overcast' => 'yes'
            ]
        ];
    }
    public function predict($features) {
        return $this->traverse($this->tree, $features);
    }
    private function traverse($node, $features) {
        // 如果是最后一个节点(决策结果)
        if (!is_array($node)) {
            return $node;
        }
        // 获取当前特征
        $feature = key($node);
        $value = $features[$feature] ?? null;
        if ($value === null) {
            return 'unknown';
        }
        // 继续递归
        if (isset($node[$feature][$value])) {
            return $this->traverse($node[$feature][$value], $features);
        }
        return 'unknown';
    }
}
// 使用示例
$tree = new SimpleDecisionTree();
$result = $tree->predict([
    'weather' => 'sunny',
    'humidity' => 'normal'
]);
echo "是否去户外: " . $result; // 输出: yes
?>

更完整的实现(含ID3算法简化版)

<?php
class ID3DecisionTree {
    private $root;
    public function build($samples, $features) {
        $this->root = $this->buildNode($samples, $features);
    }
    private function buildNode($samples, $features) {
        $labels = array_column($samples, 'label');
        // 终止条件
        if (count(array_unique($labels)) === 1) {
            return new LeafNode($labels[0]);
        }
        if (empty($features)) {
            $counts = array_count_values($labels);
            $majority = array_search(max($counts), $counts);
            return new LeafNode($majority);
        }
        // 选择最优特征(简化的信息增益)
        $bestFeature = $this->selectBestFeature($samples, $features);
        $remainingFeatures = array_diff($features, [$bestFeature]);
        $node = new InternalNode($bestFeature);
        // 分割数据
        $values = array_unique(array_column($samples, $bestFeature));
        foreach ($values as $value) {
            $subset = array_filter($samples, function($s) use ($bestFeature, $value) {
                return $s[$bestFeature] === $value;
            });
            if (empty($subset)) {
                $counts = array_count_values($labels);
                $majority = array_search(max($counts), $counts);
                $node->addChild($value, new LeafNode($majority));
            } else {
                $node->addChild($value, $this->buildNode($subset, $remainingFeatures));
            }
        }
        return $node;
    }
    private function selectBestFeature($samples, $features) {
        // 简化版:返回第一个特征
        return $features[0];
    }
    public function predict($data) {
        return $this->root->predict($data);
    }
}
class InternalNode {
    public $feature;
    public $children = [];
    public function __construct($feature) {
        $this->feature = $feature;
    }
    public function addChild($value, $node) {
        $this->children[$value] = $node;
    }
    public function predict($data) {
        $value = $data[$this->feature] ?? null;
        if ($value !== null && isset($this->children[$value])) {
            return $this->children[$value]->predict($data);
        }
        return 'unknown';
    }
}
class LeafNode {
    public $prediction;
    public function __construct($prediction) {
        $this->prediction = $prediction;
    }
    public function predict($data) {
        return $this->prediction;
    }
}
// 使用示例
$samples = [
    ['outlook' => 'sunny', 'humidity' => 'high', 'label' => 'no'],
    ['outlook' => 'sunny', 'humidity' => 'normal', 'label' => 'yes'],
    ['outlook' => 'rainy', 'humidity' => 'high', 'label' => 'no'],
    ['outlook' => 'rainy', 'humidity' => 'normal', 'label' => 'yes'],
];
$tree = new ID3DecisionTree();
$tree->build($samples, ['outlook', 'humidity']);
echo $tree->predict(['outlook' => 'sunny', 'humidity' => 'normal']); // yes
?>

推荐选择

  • 方法一:适合简单的固定规则判断
  • 方法二:适合需要动态构建和扩展的场景
  • 方法三:适合配置驱动的决策逻辑
  • 方法四:适合需要机器学习训练的场景

根据你的具体需求选择合适的方法,如果是简单的业务规则判断,方法一就够了;如果需要更复杂的机器学习功能,建议研究专门的库如php-ml。

抱歉,评论功能暂时关闭!