You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用php-ml线性回归预测Airbnb价格时遇TypeError错误求助

解决php-ml中RandomSplit的TypeError问题

问题背景

使用php-ml的最小二乘法线性回归预测2019年纽约Airbnb数据集的价格,已清理空值,剩余列顺序为index、room_type、price、minimum_nights、number_of_reviews、neighbourhood group,目标变量为price,选取minimum_nights和number_of_reviews作为特征时,执行代码触发TypeError。

错误信息

Fatal error: Uncaught TypeError:
Phpml\CrossValidation\Split::__construct(): Argument #1 ($dataset)
must be of type Phpml\Dataset\Dataset, array given, called in
C:\xampp\htdocs\490\testing2.php on line 23 and defined in
C:\xampp\htdocs\490\vendor\php-ai\php-ml\src\CrossValidation\Split.php:32
Stack trace: #0 C:\xampp\htdocs\490\testing2.php(23):
Phpml\CrossValidation\Split->__construct(Array, Array, 0.3) #1 {main}
thrown in
C:\xampp\htdocs\490\vendor\php-ai\php-ml\src\CrossValidation\Split.php
on line 32

错误触发在代码第23行:$randomSplit = new \Phpml\CrossValidation\RandomSplit($samples, $targets, 0.3);

问题代码

<?php

require 'vendor/autoload.php';

use Phpml\Regression\LeastSquares;
use Phpml\Metric\Regression;
use Phpml\CrossValidation\RandomSplit;
use Phpml\Dataset\CsvDataset;

// Load the data
$dataset = new \Phpml\Dataset\CsvDataset(filepath: "./data/NYC2019datareduced.csv", features: 5, headingRow: true);

$samples = [];
$targets = [];

foreach ($dataset->getSamples() as $sample) {
    // Selecting the features (excluding the target variable 'price')
    $samples[] = [$sample[3], $sample[4]];
    $targets[] = $sample[2];
}

// Split the data into training and testing sets
$randomSplit = new \Phpml\CrossValidation\RandomSplit($samples, $targets, 0.3);

// Train the model
$regression = new \Phpml\Regression\LeastSquares();
$regression->train($randomSplit->getTrainSamples(), $randomSplit->getTrainLabels());

// Test the model
$predicted = $regression->predict($randomSplit->getTestSamples());
$r2 = \Phpml\Metric\Regression::r2Score($randomSplit->getTestLabels(), $predicted);

echo "R2 score: $r2\n";

// Predict the price for a new listing
$newListing = [1,45]; // Replace with your own data
$predictedPrice = $regression->predict([$newListing]);

echo "Predicted price for the new listing: $predictedPrice[0]\n";

解决方案

错误原因

php-ml的RandomSplit类构造函数要求第一个参数必须是实现了Dataset接口的对象(如ArrayDataset、CsvDataset),而不是单独的样本数组和目标数组。旧版本可能支持传入数组,但新版本已调整参数要求。

修复步骤

  1. 引入ArrayDataset类,用于将手动提取的样本和目标变量包装成符合要求的Dataset对象。
  2. 用ArrayDataset包装$samples和$targets,再传入RandomSplit。

修改后的完整代码

<?php

require 'vendor/autoload.php';

use Phpml\Regression\LeastSquares;
use Phpml\Metric\Regression;
use Phpml\CrossValidation\RandomSplit;
use Phpml\Dataset\CsvDataset;
use Phpml\Dataset\ArrayDataset; // 新增引入

// Load the data
$dataset = new \Phpml\Dataset\CsvDataset(filepath: "./data/NYC2019datareduced.csv", features: 5, headingRow: true);

$samples = [];
$targets = [];

foreach ($dataset->getSamples() as $sample) {
    // 选取特征:minimum_nights(索引3)、number_of_reviews(索引4)
    $samples[] = [$sample[3], $sample[4]];
    // 目标变量:price(索引2)
    $targets[] = $sample[2];
}

// 将样本和目标变量包装为ArrayDataset对象
$arrayDataset = new ArrayDataset($samples, $targets);
// 初始化RandomSplit,传入Dataset对象和测试集占比0.3
$randomSplit = new \Phpml\CrossValidation\RandomSplit($arrayDataset, 0.3);

// 训练模型
$regression = new \Phpml\Regression\LeastSquares();
$regression->train($randomSplit->getTrainSamples(), $randomSplit->getTrainLabels());

// 测试模型并计算R2分数
$predicted = $regression->predict($randomSplit->getTestSamples());
$r2 = \Phpml\Metric\Regression::r2Score($randomSplit->getTestLabels(), $predicted);

echo "R2 score: $r2\n";

// 预测新房源价格
$newListing = [1,45]; // minimum_nights=1,number_of_reviews=45
$predictedPrice = $regression->predict([$newListing]);

echo "Predicted price for the new listing: $predictedPrice[0]\n";

另一种简化方式(直接处理CsvDataset)

如果不想手动循环提取样本,可以直接基于原始CsvDataset创建包含所需特征的子数据集,再传入RandomSplit,但需要确保目标变量的位置正确。不过手动提取样本的方式更直观,适合自定义特征选择场景。

内容的提问来源于stack exchange,提问作者Arshado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:53:14