Olá a todos!Este é o terceiro artigo sobre como presto um serviço pequeno e confortável, o que em teoria deve ajudar no planejamento de viagens. Neste artigo, falarei sobre como prever tarifas aéreas com os dados de Clickhouse, Catboost e 1 TB * em mãos.
Para que serve?
Uma das principais características do Cheappster.travel é a combinação flexível de rotas complexas (mais no artigo anterior ). Para combinar "tudo com tudo", é usado um cache agregador, no qual nem sempre os tickets são raramente pesquisados e falta muito para a criação de rotas complexas. Essa. bilhetes quentes (baratos) nos quais basear uma rota complexa para lá , mas não o suficiente 1-2 segmentos dos ingressos "normais" (pelo preço normal, não na direção mais popular). Foi esse problema que me levou à necessidade de construir um modelo que pudesse prever a passagem aérea.Formalização de tarefas
- Você precisa prever bilhetes para voos diretos (apenas ida e volta)
- Você precisa prever e armazenar isso regularmente no banco de dados (cenário simples)
- Precisa ser capaz de prever "on the fly" (cenário complexo)
- Isso tudo acontece em um hardware muito limitado - portanto, um mínimo de manipulação com grandes quantidades de dados
Como fazer isso?
Para começar, treinaremos o modelo: prepare o conjunto de dados, destacando o número máximo de recursos nas colunas, faça o upload para tsv, carregue-o no DataFrame / Pool, analise, selecione os parâmetros ... Pare, temos muitos dados e eles não cabem na memória , - pegue os seguintes erros:MemoryError: Unable to allocate array with shape (38, 288224989) and data type float64
OSError: [Errno 12] Cannot allocate memory
Para contornar essa limitação, era necessário aprender iterativamente em pedaços pequenos, assim:model = CatBoostRegressor(cat_features=cat_features,
iterations=100,
learning_rate=.5,
depth=10,
l2_leaf_reg=9,
one_hot_max_size=5000)
for df in tqdm(pd.read_csv('history.tsv', sep='\t',
na_values=['\\N'],
chunksize=2_000_000)):
...
model.fit(X=df[df.columns[:-1]][:train_size].values,
y=df['price'][:train_size].values,
eval_set=eval_pool,
verbose=False,
plot=False,
init_model=model)
O resultado foi um modelo com RMSE ~ 100 - em geral, eu ficaria feliz com esse resultado, mas depois de uma pequena análise e "normalização" das previsões (negativos e valores que diferem muito dos valores mín / máx na história são levados para os limites correspondentes dos preços históricos) . Depois disso, a métrica de destino é ~ 80, levando em consideração o fato de que, na minha experiência, quase não há lógica e bom senso no preço de passagens aéreas.Recursos que afetam o preço mais:
Estatísticas dos recursos “Distância entre cidades”:
Ótimo, temos um modelo - agora é hora de usá-lo. Primeiro de tudo, adicione o modelo KX, isso é feito com uma configuração simples:Config<models>
<model>
<type>catboost</type>
<name>price</name>
<path>/opt/models/price_iter_model_2.bin</path>
<lifetime>0</lifetime>
</model>
</models>
Fazemos um processo de previsão regular - é fácil o suficiente usando o Apache Airflow.O DAG resultante se parece com isso
DAGa ( Airflow):
SimpleHttpOperatorinsert_ow_in_tmp = SimpleHttpOperator(
task_id='insert_ow_in_tmp',
http_conn_id='clickhouse_http',
endpoint=dll_endpoint,
method='POST',
data=sql_templates.INSERT_OW_PREDICTIONS_IN_TMP,
pool='clickhouse_select',
dag=dag
)
Para previsão "on the fly" usando sql comum:select origin, destination, date,
modelEvaluate('price', *) predicted_price
from log.history
+
| origin | destination | date | predicted_price |
+
| VKO | DEB | 2020-03-20 | 3234.43244 |
+
Quero substituir o fato de que essa abordagem foi escolhida, não apenas porque é mais fácil de implementar - ainda há vantagens:- Não é necessário fazer upload de dados para o exterior do KH (isso significa mais rápido e menos dispendioso com a carga no ferro)
- Não há necessidade de executar processos etl (mais fácil = mais confiável)
Corrigimos um pouco a API e o front-end e obtivemos as previsões há muito esperadas.Essas previsões também se encaixam bem na seção Histórico de preços de passagens aéreas : a
funcionalidade está disponível em cheappster.travel/history (será aberta de maneira torta no celular, apenas em telas grandes).Isso é tudo, um dia produtivo!Artigos anteriores
Uma tentativa de resolver o problema de escolher passagens aéreas antes das fériasUma tentativa de resolver o problema de escolher passagens aéreas antes das férias # 2Outra característica interessante
Combinador de rotas difíceisBilhetes complexos (triângulos)PSImportante! Não tome essas previsões como algo que o ajude a escolher uma data de compra - o modelo pode não prever corretamente, além disso, sua adequação não foi verificada por mim ou por qualquer outra pessoa (tudo por seu próprio risco e risco, sem garantias).1 TB * - isto é, se você fizer o upload para tsv, no KX é preciso uma ordem de magnitude menor.UPD:Principais problemas não óbvios ao usar pacotes Catboost - Clickhouse
- Os recursos categóricos no KH alteram a ordem e se tornam no final (e não na ordem que estava durante o treinamento);
- modelEvaluate retorna null - você precisa verificar se possui valores nulos nos recursos, se precisar substituí-los por nan
- Nas novas versões, há um momento não óbvio com o formato de configuração para o KX, descrito aqui