我在scikit-learn中创建了一个机器学习模型,我需要在生产中使用实时数据进行部署。这些功能如下所示:
date event_id user_id feature1 feature2 featureX...
2017-01-27 100 5555 1.23 2 2.99
2017-01-27 100 4444 2.55 5 3.16
2017-01-27 100 3333 0.45 3 1.69
2017-01-27 105 1212 3.96 4 0.0
2017-01-27 105 2424 1.55 2 5.56
2017-01-27 105 3636 0.87 4 10.28
因此,每天都有不同的事件。在事件开始之前,我基本上将它存储在数据框中,方法是将它们从数据库中拉出来,然后使用pickle scikit模型计算预测:
df_X = df.drop(['date', 'event_id', 'user_id'], axis=1)
loaded_model = joblib.load("model.joblib.dat")
prediction = loaded_model.predict_proba(df_X)
然后我将预测与df匹配,并根据需要将其作为输出发送到API或文件。
当事件开始时,我会从API中不断更新featureX
。要进行更新,请使用遍历每个event_id
和user_id
的循环,并使用新的df
值更新featureX
,重新计算并发送到输出试。
为此,我做了这样的事情:
# get list of unique event ids
events = set(df['event_id'].tolist())
try:
while True:
start = time.time()
for event in events:
featureX = request.get(API_URL + event)
featureX_json = featureX.json()
for user in featureX_json['users']:
df.loc[df.user_id == user['user_id'],
'featureX'] = user['featureX']
df_X = df.drop(['date', 'event_id', 'user_id'], axis=1)
df['prediction'] = loaded_model.predict_proba(df_X)
# send to API or write to file
end = time.time()
print('recalculation time {} secs'.format(end - start))
except KeyboardInterrupt:
print('exiting !')
这对我来说很好,但整个预测更新在服务器中需要大约4秒,我需要它在1秒内。我试图找出while loop
中我可以改变的内容以获得我需要的加速?
根据event_id = 100
网址http://myapi/api/event_users/<event_id>
的要求添加了json示例:
{
"count": 3,
"users": [
{
"user_id": 4444,
"featureY": 34,
"featureX": 4.49,
"created": "2017-01-17T13:00:09.065498Z"
},
{
"user_id": 3333,
"featureY": 22,
"featureX": 1.09,
"created": "2017-01-17T13:00:09.065498Z"
},
{
"user_id": 5555,
"featureY": 58,
"featureX": 9.54,
"created": "2017-01-17T13:00:09.065498Z"
}
]
}
答案 0 :(得分:1)
# get list of unique event ids
events = df['event_id'].unique().tolist()
try:
while True: # i don't understand why do you need this loop...
start = time.time()
for event in events:
featureX = request.get(API_URL + event)
tmp = pd.DataFrame(featureX.json()['users'])
df.loc[(df.event_id == event), 'featureX'] = \
df.loc[df.event_id == event, 'user_id'] \
.map(tmp.set_index('user_id').featureX)
df_X = df.drop(['date', 'event_id', 'user_id'], axis=1)
df['prediction'] = loaded_model.predict_proba(df_X)
# send to API or write to file
end = time.time()
print('recalculation time {} secs'.format(end - start))
except KeyboardInterrupt:
print('exiting !')
演示:event_id == 100
首先让你的JSON对象创建一个DF:
tmp = pd.DataFrame(featureX_json['users'])
In [33]: tmp
Out[33]:
created featureX featureY user_id
0 2017-01-17T13:00:09.065498Z 4.49 34 4444
1 2017-01-17T13:00:09.065498Z 1.09 22 3333
2 2017-01-17T13:00:09.065498Z 9.54 58 5555
现在我们可以摆脱for user in featureX_json['users']:
循环:
In [29]: df.loc[df.event_id == 100, 'featureX'] = \
df.loc[df.event_id == 100, 'user_id'].map(tmp.set_index('user_id').featureX)
In [30]: df
Out[30]:
date event_id user_id feature1 feature2 featureX
0 2017-01-27 100 5555 1.23 2 9.54 # 2.99 -> 9.54
1 2017-01-27 100 4444 2.55 5 4.49 # 3.16 -> 4.49
2 2017-01-27 100 3333 0.45 3 1.09 # 1.69 -> 1.09
3 2017-01-27 105 1212 3.96 4 0.00
4 2017-01-27 105 2424 1.55 2 5.56
5 2017-01-27 105 3636 0.87 4 10.28
答案 1 :(得分:0)
最好订阅某种消息队列,例如Kafka。然后,您可以在FeatureX
进行更新时使用它,而不是无休止地在循环中进行批处理API调用,然后遍历整个数据源,等等。
关于预测,可能需要采用更具扩展性的方法。您可以将数据帧分成多个块,并向可扩展的高吞吐量预测API发出异步请求。使用这种方法,您仅受网络延迟和可以同时发出多少个请求的限制。如果预测API可以每秒处理数千个/ 10k / 100k的请求,那么您的预测时间可以减少到不到一秒(可能只有几百毫秒)。
我的服务mlrequest是一种低延迟,高吞吐量,高可用性的机器学习API,非常适合此类问题。我们可以处理和扩展到每秒很多很多的预测。下一个版本(即将推出)将支持Scikit Learn模型和Pandas Dataframe。以下是训练和预测的简单示例。您可以获得free api key,每月可进行50,000个模型交易。
安装mlrequest Python客户端
$pip install mlrequest
训练模型并将其部署到全球5个数据中心非常简单:
from mlrequest import Classifier
classifier = Classifier('my-api-key')
features = {'feature1': 'val1','feature2': 100}
training_data = [{'features': features, 'label': 1}, ...]
r = classifier.learn(training_data=training_data, model_name='my-model', class_count=2)
预测
features = [{'feature1': 'val1', 'feature2': 77}, ...]
r = classifier.predict(features=features, model_name='my-model', class_count=2)
r.predict_result