前言
系列专栏:【深度学习:算法项目实战】✨︎
涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记忆、自然语言处理、深度强化学习、大型语言模型和迁移学习。
对于送餐服务公司来说,预测订单的送达时间是一项极具挑战性的任务。像 Zomato 和 Swiggy 这样的食品外卖服务需要准确显示送达订单所需的时间,以保持对客户的透明度。这些公司使用机器学习算法,根据送餐员过去在相同距离上所花费的时间来预测送餐时间。因此,如果您想了解如何使用机器学习预测食品配送时间,本文就是为您准备的。本文将带你使用 Python 通过机器学习预测送餐时间。
目录
- 1. 相关数据集
- 1.1 导入必要库
- 1.2 加载数据集
- 2. 计算两个经纬度之间的距离
- 3. 探索性分析
- 3.1 送餐距离和送餐时间
- 3.2 送餐时间与送餐员年龄
- 3.3 送餐时间与送餐员评级
- 3.4 食物类型与车辆类型
- 4. 时间预测模型
- 4.1 准备数据
- 4.2 构建模型(LSTM)
- 4.3 模型训练
- 4.4 模型评估
- 5. 总结
1. 相关数据集
要实时预测食品配送时间,我们需要计算餐厅与送餐地点之间的距离。在找到餐厅和送餐地点之间的距离后,我们需要找到送餐员过去在相同距离内送餐所用时间之间的关系。因此,为了完成这项任务,我们需要一个数据集,其中包含送餐员从餐厅到送餐地点的送餐时间数据。
这里提供的数据集是 Gaurav Malik 在 Kaggle 上提交的原始数据集的净化版本。
以下是数据集中的所有特征:🔗
- ID: 订单 ID 编号
- Delivery_person_ID: 送餐员的 ID 编号
- Delivery_person_Age: 送餐员的年龄
- Delivery_person_Ratings(送餐人员评分): 根据以往送餐情况对送餐员的评分
- Restaurant_latitude: 餐厅的纬度
- Restaurant_longitude: 餐厅的经度
- Delivery_location_latitude: 送餐地点的纬度
- Delivery_location_longitude: 送餐地点的经度
- Type_of_order: 顾客订购的餐食类型
- Type_of_vehicle:送餐员所乘坐车辆的类型
- Time_taken(min): 送餐员完成订单所需的时间
1.1 导入必要库
我将通过导入必要的 Python 库和数据集来开始送餐时间预测任务:
import numpy as np
import pandas as pd
import plotly.express as px
#splitting data
from sklearn.model_selection import train_test_split
# creating the LSTM neural network model
from keras.models import Sequential
from keras.layers import Input, Dense, LSTM
1.2 加载数据集
①使用 pandas 函数 .read_csv()
加载数据集
data = pd.read_csv("deliverytime.txt")
print(data.head())
ID Delivery_person_ID Delivery_person_Age Delivery_person_Ratings \
0 4607 INDORES13DEL02 37 4.9
1 B379 BANGRES18DEL02 34 4.5
2 5D6D BANGRES19DEL01 23 4.4
3 7A6A COIMBRES13DEL02 38 4.7
4 70A2 CHENRES12DEL01 32 4.6
Restaurant_latitude Restaurant_longitude Delivery_location_latitude \
0 22.745049 75.892471 22.765049
1 12.913041 77.683237 13.043041
2 12.914264 77.678400 12.924264
3 11.003669 76.976494 11.053669
4 12.972793 80.249982 13.012793
Delivery_location_longitude Type_of_order Type_of_vehicle Time_taken(min)
0 75.912471 Snack motorcycle 24
1 77.813237 Snack scooter 33
2 77.688400 Drinks motorcycle 26
3 77.026494 Buffet motorcycle 21
4 80.289982 Snack scooter 30
接下来,让我们来看看每一列数据的具体信息
②使用 .info()
方法打印有关DataFrame的信息,包括索引dtype
和列、非null
值以及内存使用情况
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 45593 entries, 0 to 45592
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ID 45593 non-null object
1 Delivery_person_ID 45593 non-null object
2 Delivery_person_Age 45593 non-null int64
3 Delivery_person_Ratings 45593 non-null float64
4 Restaurant_latitude 45593 non-null float64
5 Restaurant_longitude 45593 non-null float64
6 Delivery_location_latitude 45593 non-null float64
7 Delivery_location_longitude 45593 non-null float64
8 Type_of_order 45593 non-null object
9 Type_of_vehicle 45593 non-null object
10 Time_taken(min) 45593 non-null int64
dtypes: float64(5), int64(2), object(4)
memory usage: 3.8+ MB
③现在我们来看看这个数据集是否包含任何空值:
data.isnull().sum()
ID 0
Delivery_person_ID 0
Delivery_person_Age 0
Delivery_person_Ratings 0
Restaurant_latitude 0
Restaurant_longitude 0
Delivery_location_latitude 0
Delivery_location_longitude 0
Type_of_order 0
Type_of_vehicle 0
Time_taken(min) 0
dtype: int64
数据集没有任何空值。让我们继续!
2. 计算两个经纬度之间的距离
数据集没有任何特征可以显示餐厅和送餐地点之间的差异。我们只有餐厅和送餐地点的经纬度点。我们可以使用哈弗辛公式,根据两个地点的经纬度计算它们之间的距离。
下面是我们如何根据餐厅和外卖地点的经纬度,利用哈弗辛公式求出它们之间的距离:
# Set the earth's radius (in kilometers)
R = 6371
# Convert degrees to radians
def deg_to_rad(degrees):
return degrees * (np.pi/180)
# Function to calculate the distance between two points using the haversine formula
def distcalculate(lat1, lon1, lat2, lon2):
d_lat = deg_to_rad(lat2-lat1)
d_lon = deg_to_rad(lon2-lon1)
a = np.sin(d_lat/2)**2 + np.cos(deg_to_rad(lat1)) * np.cos(deg_to_rad(lat2)) * np.sin(d_lon/2)**2
c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1-a))
return R * c
# Calculate the distance between each pair of points
data['distance'] = np.nan
for i in range(len(data)):
data.loc[i, 'distance'] = distcalculate(data.loc[i, 'Restaurant_latitude'],
data.loc[i, 'Restaurant_longitude'],
data.loc[i, 'Delivery_location_latitude'],
data.loc[i, 'Delivery_location_longitude'])
现在,我们已经计算出餐厅与送餐地点之间的距离。我们还在数据集中添加了一个新特征,即距离。让我们再次查看数据集:
print(data.head())
ID Delivery_person_ID Delivery_person_Age Delivery_person_Ratings \
0 4607 INDORES13DEL02 37 4.9
1 B379 BANGRES18DEL02 34 4.5
2 5D6D BANGRES19DEL01 23 4.4
3 7A6A COIMBRES13DEL02 38 4.7
4 70A2 CHENRES12DEL01 32 4.6
Restaurant_latitude Restaurant_longitude Delivery_location_latitude \
0 22.745049 75.892471 22.765049
1 12.913041 77.683237 13.043041
2 12.914264 77.678400 12.924264
3 11.003669 76.976494 11.053669
4 12.972793 80.249982 13.012793
Delivery_location_longitude Type_of_order Type_of_vehicle Time_taken(min) \
0 75.912471 Snack motorcycle 24
1 77.813237 Snack scooter 33
2 77.688400 Drinks motorcycle 26
3 77.026494 Buffet motorcycle 21
4 80.289982 Snack scooter 30
distance
0 3.025149
1 20.183530
2 1.552758
3 7.790401
4 6.210138
3. 探索性分析
3.1 送餐距离和送餐时间
现在,让我们探索数据,找出特征之间的关系。我先来看看送餐距离和送餐时间之间的关系:
figure = px.scatter(data_frame = data,
x="distance",
y="Time_taken(min)",
size="Time_taken(min)",
trendline="ols",
title = "Relationship Between Distance and Time Taken")
figure.show()
送餐时间与送餐距离之间存在一致的关系。也就是说,无论距离远近,大多数送餐员都能在 25-30 分钟内送达食物。
3.2 送餐时间与送餐员年龄
现在我们来看看送餐时间与送餐员年龄之间的关系:
figure = px.scatter(data_frame = data,
x="Delivery_person_Age",
y="Time_taken(min)",
size="Time_taken(min)",
color = "distance",
trendline="ols",
title = "Relationship Between Time Taken and Age")
figure.show()
送餐时间与送餐员的年龄呈线性关系。这意味着年轻的送餐员比年长的送餐员用时更短。
3.3 送餐时间与送餐员评级
现在让我们来看看送餐时间与送餐员评级之间的关系:
figure = px.scatter(data_frame = data,
x="Delivery_person_Ratings",
y="Time_taken(min)",
size="Time_taken(min)",
color = "distance",
trendline="ols",
title = "Relationship Between Time Taken and Ratings")
figure.show()
送餐时间与送餐员的评分之间存在反向线性关系。也就是说,与评分低的送餐员相比,评分高的送餐员送餐时间更短。
3.4 食物类型与车辆类型
现在我们来看看顾客订购的食物类型和送餐员使用的车辆类型是否会影响送餐时间:
fig = px.box(data,
x="Type_of_vehicle",
y="Time_taken(min)",
color="Type_of_order")
fig.show()
因此,送餐员所花费的时间并不会因为他们所驾驶的车辆和所运送的食品类型而有太大差异。
因此,根据我们的分析,对送餐时间影响最大的特征是:
- 送餐员的年龄
- 送餐员的评级
- 餐厅与送餐地点之间的距离
4. 时间预测模型
4.1 准备数据
将数据拆分为训练集和测试集
#splitting data
from sklearn.model_selection import train_test_split
x = np.array(data[["Delivery_person_Age",
"Delivery_person_Ratings",
"distance"]])
y = np.array(data[["Time_taken(min)"]])
xtrain, xtest, ytrain, ytest = train_test_split(x, y,
test_size=0.10,
random_state=42)
4.2 构建模型(LSTM)
现在,让我们使用 LSTM 神经网络模型来训练一个机器学习模型,以完成送餐时间预测任务:
# creating the LSTM neural network model
from keras.models import Sequential
from keras.layers import Input, Dense, LSTM
model = Sequential([
Input(shape=(xtrain.shape[1], 1)),
LSTM(128, return_sequences=True),
LSTM(64, return_sequences=False),
Dense(25),
Dense(1)
])
model.compile(optimizer='adam', loss='mean_squared_error')
model.summary()
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ lstm (LSTM) │ (None, 3, 128) │ 66,560 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ lstm_1 (LSTM) │ (None, 64) │ 49,408 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense (Dense) │ (None, 25) │ 1,625 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense_1 (Dense) │ (None, 1) │ 26 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
Total params: 117,619 (459.45 KB)
Trainable params: 117,619 (459.45 KB)
Non-trainable params: 0 (0.00 B)
4.3 模型训练
model.fit(xtrain, ytrain, batch_size=1, epochs=9)
Epoch 1/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 65s 2ms/step - loss: 78.0635
Epoch 2/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 63s 2ms/step - loss: 65.2568
Epoch 3/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 62s 2ms/step - loss: 61.7881
Epoch 4/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 62s 2ms/step - loss: 60.5413
Epoch 5/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 63s 2ms/step - loss: 60.2824
Epoch 6/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 63s 2ms/step - loss: 59.3861
Epoch 7/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 62s 2ms/step - loss: 59.8831
Epoch 8/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 62s 2ms/step - loss: 59.0806
Epoch 9/9
41033/41033 ━━━━━━━━━━━━━━━━━━━━ 63s 2ms/step - loss: 59.7611
4.4 模型评估
现在,让我们通过输入来预测送餐时间,从而测试模型的性能:
print("Food Delivery Time Prediction")
a = int(input("Age of Delivery Partner: "))
b = float(input("Ratings of Previous Deliveries: "))
c = int(input("Total Distance: "))
features = np.array([[a, b, c]])
print("Predicted Delivery Time in Minutes = ", model.predict(features))
Food Delivery Time Prediction
Age of Delivery Partner: 29
Ratings of Previous Deliveries: 2.9
Total Distance: 6
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 155ms/step
Predicted Delivery Time in Minutes = [[35.726112]]
5. 总结
要实时预测食品配送时间,需要计算食品准备点与食品消费点之间的距离。在找到餐厅和送餐地点之间的距离后,您需要找到送餐员过去在相同距离内的送餐时间之间的关系。希望您喜欢这篇关于使用 Python 进行机器学习预测送餐时间的文章。