纽约出租车计费问题:一个简单的线性模型
机器学习案例详解的直播互动平台——
机器学习训练营(qq群号:696721295)
下期直播案例预告:大数据预测商品的销售量波动趋势
案例背景
该案例是一个美国纽约市出租车的行程计费问题。给定乘客上、下车的位置信息,你要根据行程距离,建立模型预测出租车的车费。该模型可以扩展应用于出租车车费定价、阶梯价格设定等问题。
-
案例来源: Google云课程
-
代码实现: Python
数据描述
ID
- key 行识别符字符串。
特征
-
pickup_datetime 出租车行程开始时间
-
pickup_longitude 出租车行程开始经度坐标
-
pickup_latitude 出租车行程开始纬度坐标
-
dropoff_longitude 出租车行程结束经度坐标
-
dropoff_latitude 出租车行程结束纬度坐标
-
passenger_count 乘客数
目标变量
- fare_amount 车费
数据准备
我们想在训练集train.csv
上建立预测模型,所以首先加载训练数据。由于整个训练集特别庞大,共有55M行。根据内存容量大小,我们选择加载100万行的数据子集。
# Initial Python environment setup...
import numpy as np # linear algebra
import pandas as pd # CSV file I/O (e.g. pd.read_csv)
import os # reading the input files we have access to
train_df = pd.read_csv('../input/train.csv', nrows = 10_000_000)
print(train_df.dtypes)
我们想使用经度、纬度坐标定义一个行程向量。为此,我们产生两个新的特征,分别表示经度、纬度的距离。
# Given a dataframe, add two new features 'abs_diff_longitude' and
# 'abs_diff_latitude' reprensenting the "Manhattan vector" from
# the pickup location to the dropoff location.
def add_travel_vector_features(df):
df['abs_diff_longitude'] = (df.dropoff_longitude - df.pickup_longitude).abs()
df['abs_diff_latitude'] = (df.dropoff_latitude - df.pickup_latitude).abs()
add_travel_vector_features(train_df)
print(train_df.head())
删除缺失行
我们看一看训练集里是否有缺失项(NaN
)
print(train_df.isnull().sum())
由于缺失项很少,我们直接删除它们所在的数据行。
print('Old size: %d' % len(train_df))
train_df = train_df.dropna(how = 'any', axis = 'rows')
print('New size: %d' % len(train_df))
线性模型
我们在训练集上建立一个简单的线性模型预测车费。模型定义为
其中,是输入特征矩阵,由两个GPS坐标差和1向量组成。是目标变量fare_amount
, 是估计向量。我们写一个函数组建这些。
# Construct and return an Nx3 input matrix for our linear model
# using the travel vector, plus a 1.0 for a constant bias term.
def get_input_matrix(df):
return np.column_stack((df.abs_diff_longitude, df.abs_diff_latitude, np.ones(len(df))))
train_X = get_input_matrix(train_df)
train_y = np.array(train_df['fare_amount'])
print(train_X.shape)
print(train_y.shape)
现在,我们使用numpy的lstsq库函数找到最优的权向量.
# The lstsq function returns several things, and we only care about the actual weight vector w.
(w, _, _, _) = np.linalg.lstsq(train_X, train_y, rcond = None)
print(w)
它实际上等价于的最小二乘估计:
w_OLS = np.matmul(np.matmul(np.linalg.inv(np.matmul(train_X.T, train_X)), train_X.T), train_y)
print(w_OLS)
现在,我们可以加载检验集,并将该模型用于检验集上预测车费。
改善的想法
- 使用输入数据里的更多特征。
这里,我们仅使用了开始/结束的GPS坐标。可以尝试加入乘车时间、乘客数等特征改善模型。
- 使用绝对坐标而不是相对坐标。
这里,我们仅使用了开始到结束点的距离。可以考虑上、下车的GPS坐标作为预测变量。
-
排除离群点。
-
使用完整的数据集。