Machine Learning记录1

2026年1月22日 5点热度 0人点赞 0条评论

记录写kaggle练习时记录的东西

最基础的决策树模型

下面是假设:

你的表弟靠房地产投机赚了数百万美元。他因为你对数据科学感兴趣,所以提出和你合伙做生意。他出资,你则提供预测不同房屋价值的模型。

你问表弟过去是如何预测房产价值的,他说只是凭直觉。但进一步询问后发现,他其实是从过去看过的房子中总结出了价格规律,并利用这些规律来预测他正在考虑的新房的价格。

机器学习的工作原理也类似。我们将从一种叫做决策树的模型开始。虽然还有更高级的模型可以给出更准确的预测,但决策树易于理解,并且是数据科学领域一些最佳模型的基础构建模块。

它将房屋仅分为两类。任何待评估房屋的预测价格都是同类房屋的历史平均价格。

我们利用数据决定如何将房屋分成两组,然后再确定每组的预测价格。从数据中捕捉模式的这一步骤称为模型拟合训练 。用于拟合模型的数据称为训练数据 

你可以使用具有更多“分支”的决策树来捕捉更多因素。这些决策树被称为“深层”决策树。例如,一个同时考虑每栋房屋地块总面积的决策树可能如下所示:

预测任何房屋的价格,只需遍历决策树,始终选择与该房屋特征相对应的路径即可。预测的房屋价格位于决策树的底部。我们进行预测的底部点称为叶子节点。

一些Python和库的基本操作

Pandas 库中最重要的部分是 DataFrame。DataFrame 存储的数据类型类似于表格。这类似于 Excel 中的工作表或 SQL 数据库中的表。Pandas 为处理此类数据的大部分需求提供了强大的方法。

例如,我们将查看澳大利亚墨尔本的房价数据 。在实践练习中,您将把相同的流程应用到一个新的数据集,该数据集包含爱荷华州的房价数据。

示例(墨尔本)数据位于文件路径 ../input/melbourne-housing-snapshot/melb_data.csv 

我们使用以下命令加载和探索数据:

# save filepath to variable for easier access</em>
melbourne_file_path = '../input/melbourne-housing-snapshot/melb_data.csv'
# read the data and store data in DataFrame titled melbourne_data</em>
melbourne_data = pd.read_csv(melbourne_file_path) 
# print a summary of the data in Melbourne data</em>
melbourne_data.describe()

Rooms
PriceDistancePostcodeBedroom2BathroomCarLandsizeBuildingAreaYearBuiltLattitudeLongtitudePropertycount
count13580.0000001.358000e+0413580.00000013580.00000013580.00000013580.00000013518.00000013580.0000007130.0000008205.00000013580.00000013580.00000013580.000000
mean2.9379971.075684e+0610.1377763105.3019152.9147281.5342421.610075558.416127151.9676501964.684217-37.809203144.9952167454.417378
std0.9557486.393107e+055.86872590.6769640.9659210.6917120.9626343990.669241541.01453837.2737620.0792600.1039164378.581772
min1.0000008.500000e+040.0000003000.0000000.0000000.0000000.0000000.0000000.0000001196.000000-38.182550144.431810249.000000
25%2.0000006.500000e+056.1000003044.0000002.0000001.0000001.000000177.00000093.0000001940.000000-37.856822144.9296004380.000000
50%3.0000009.030000e+059.2000003084.0000003.0000001.0000002.000000440.000000126.0000001970.000000-37.802355145.0001006555.000000
75%3.0000001.330000e+0613.0000003148.0000003.0000002.0000002.000000651.000000174.0000001999.000000-37.756400145.05830510331.000000
max10.0000009.000000e+0648.1000003977.00000020.0000008.00000010.000000433014.00000044515.0000002018.000000-37.408530145.52635021650.000000

数据集包含太多变量,你难以理解,甚至无法清晰地打印出来。如何才能将这些海量数据精简成你能理解的形式?我们将首先凭直觉选择几个变量。要选择变量/列,我们需要查看数据集中的所有列。这可以通过 DataFrame 的 columns 属性完成(如下代码的最后一行)。

melbourne_data.columns
Index(['Suburb', 'Address', 'Rooms', 'Type', 'Price', 'Method', 'SellerG',
       'Date', 'Distance', 'Postcode', 'Bedroom2', 'Bathroom', 'Car',
       'Landsize', 'BuildingArea', 'YearBuilt', 'CouncilArea', 'Lattitude',
       'Longtitude', 'Regionname', 'Propertycount'],
      dtype='object')

你可以使用点号表示法提取变量。这一列存储在 Series 中,它与 DataFrame 非常相似,只是只有一列数据。我们将使用点号表示法来选择要预测的列,这列被称为预测目标 。按照惯例,预测目标被称为 y 。

y = melbourne_data.Price

输入到模型中的列(之后用于进行预测)被称为“特征”。在本例中,这些特征就是用于确定房价的列。有时,除了目标值之外的所有列都会被用作特征。而有时,使用较少的特征效果会更好。

现在,我们将构建一个只包含少量特征的模型。稍后您将看到如何迭代并比较使用不同特征构建的模型。

我们通过在方括号内提供列名列表来选择多个特征。列表中的每一项都应该是一个字符串(带引号)。按照惯例,这些数据被称为 X。

melbourne_features = ['Rooms', 'Bathroom', 'Landsize', 'Lattitude', 'Longtitude']
X = melbourne_data[melbourne_features]

构建和使用模型的步骤如下:

  • 明确定义: 模型类型是什么?决策树?还是其他类型的模型?模型类型的其他一些参数也已指定。
  • 拟合: 从提供的数据中捕捉模式。这是建模的核心。
  • 对得到的模型进行预测
  • 评估 :确定模型预测的准确性。
from sklearn.tree import DecisionTreeRegressor

# Define model. Specify a number for random_state to ensure same results each run
melbourne_model = DecisionTreeRegressor(random_state=1)

# Fit model
melbourne_model.fit(X, y)

许多机器学习模型允许在模型训练过程中存在一定的随机性。为 random_state 指定一个数值可以确保每次运行都得到相同的结果。这被认为是一种良好的实践。你可以使用任意数值,模型质量不会显著依赖于你选择的具体值。

模型验证(Only MAE)

几乎你构建的每一个模型都需要进行评估。在大多数(但并非所有)应用中,衡量模型质量的相关指标是预测准确率。换句话说,就是模型的预测结果是否接近实际情况。很多人在衡量预测准确率时会犯一个巨大的错误。他们用训练数据进行预测,然后将这些预测值与训练数据中的目标值进行比较。稍后您就会看到这种方法的弊端以及如何解决它,但我们先来思考一下应该如何操作。

首先,你需要用一种易于理解的方式概括模型的质量。如果你比较1万套房屋的预测房价和实际房价,很可能会发现预测结果好坏参半。逐一查看这1万个预测值和实际值的列表毫无意义。我们需要将其概括为一个单一的指标。有很多指标可以用来概括模型质量,但我们先从一个名为平均绝对误差 (也称 MAE )的指标开始。

使用平均绝对误差 (MAE) 指标时,我们取每个误差的绝对值,将每个误差转换为正数。然后,我们计算这些绝对误差的平均值。这就是我们衡量模型质量的指标。简单来说,可以这样表述:平均而言,我们的预测误差约为 X。

可以通过sklearn库中的自带的函数进行调用

from sklearn.metrics import mean_absolute_error

predicted_home_prices = melbourne_model.predict(X)
mean_absolute_error(y, predicted_home_prices)

由于模型的实际价值在于对新数据进行预测,因此我们会评估模型在未用于构建模型的数据上的性能。最直接的方法是将部分数据从模型构建过程中排除,然后用这些数据来测试模型在之前未见过的数据上的准确性。这些数据被称为验证数据,划分验证数据的时候要注意等比例划分。

scikit-learn 库有一个函数 train_test_split ,可以将数据按等比例分成两部分。我们将使用其中一部分数据作为训练数据来拟合模型,并将另一部分数据作为验证数据来计算 mean_absolute_error 。

from sklearn.model_selection import train_test_split

# split data into training and validation data, for both features and target
# The split is based on a random number generator. Supplying a numeric value to
# the random_state argument guarantees we get the same split every time we
# run this script.
train_X, val_X, train_y, val_y = train_test_split(X, y, random_state = 0)
# Define model
melbourne_model = DecisionTreeRegressor()
# Fit model
melbourne_model.fit(train_X, train_y)

# get predicted prices on validation data
val_predictions = melbourne_model.predict(val_X)
print(mean_absolute_error(val_y, val_predictions))

欠拟合和过拟合(Underfitting and Overfitting)

实际上,一棵树从顶层(所有房屋)到叶子节点之间有 10 个分支的情况并不少见。随着树的深度增加,数据集会被分割成越来越多的叶子节点,每个叶子节点包含的房屋数量也会减少。如果一棵树只有 1 个分支,它会将数据分成 2 组。如果每组再被分割一次,就会得到 4 组房屋。再将每组房屋分割一次,就会得到 8 组。如果我们通过在每一层都增加分支来不断增加组数,那么到第 10 层时,我们将得到 2^10也就是1024个节点

当我们把房屋分散到许多叶子上时,每个叶子上的房屋数量也会减少。房屋数量很少的叶子做出的预测会非常接近这些房屋的实际价值,但它们对新数据的预测可能非常不可靠(因为每个预测都只基于少数房屋)。这是一种称为过拟合的现象,即模型几乎完美地拟合了训练数据,但在验证集和其他新数据上的表现却很差。

另一方面,如果我们把决策树做得非常浅,它就无法将房屋划分成非常清晰的组别。极端情况下,如果一棵树只将房屋分成 2 或 4 组,每组房屋的种类仍然非常丰富。这样一来,即使在训练数据中,大多数房屋的预测结果也可能与实际情况相差甚远(同样的原因,在验证集上也会表现不佳)。当模型无法捕捉数据中重要的差异和模式,以至于即使在训练数据上表现也很差时,这种情况称为欠拟合。

控制决策树深度的方法有很多,许多方法允许树中的某些路径比其他路径更深。但 `max_leaf_nodes` 参数提供了一种非常合理的方法来控制过拟合和欠拟合。我们允许模型生成的叶子节点越多,模型就越容易从上图中的欠拟合区域向过拟合区域移动。我们可以使用实用函数来帮助比较不同 max_leaf_nodes 值下的 MAE 得分:

from sklearn.metrics import mean_absolute_error
from sklearn.tree import DecisionTreeRegressor

def get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y):
    model = DecisionTreeRegressor(max_leaf_nodes=max_leaf_nodes, random_state=0)
    model.fit(train_X, train_y)
    preds_val = model.predict(val_X)
    mae = mean_absolute_error(val_y, preds_val)
    return(mae)

我们可以使用 for 循环来比较使用不同 max_leaf_nodes 值构建的模型的准确性。

for max_leaf_nodes <strong>in</strong> [5, 50, 500, 5000]:
    my_mae = get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y)
    print("Max leaf nodes: %dMean Absolute Error:%d" %(max_leaf_nodes, my_mae))

随机森林

随机森林使用许多决策树,并通过对每棵树的预测结果取平均值来进行预测。它通常比单个决策树具有更高的预测精度,并且在默认参数下也能很好地工作。如果持续建模,可以学习到性能更优的更多模型,但其中许多模型对参数的设置非常敏感。

我们构建随机森林模型的方式与在 scikit-learn 中构建决策树的方式类似——这次使用的是 RandomForestRegressor 类而不是 DecisionTreeRegressor 类。

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error

forest_model = RandomForestRegressor(random_state=1)
forest_model.fit(train_X, train_y)
melb_preds = forest_model.predict(val_X)
print(mean_absolute_error(val_y, melb_preds))

MuWinds

这个人很懒,什么都没留下

文章评论