专栏首页ATYUN订阅号机器学习项目:建立一个酒店推荐引擎

机器学习项目:建立一个酒店推荐引擎

编译:yxy

出品:ATYUN订阅号

所有在线旅行社都在争先恐后地满足亚马逊和网飞(Netflix)设定的AI驱动的个性化标准。此外,在线旅游已经成为一个竞争激烈的领域,品牌试图通过推荐,对比,匹配和分享来吸引我们的注意力(和钱包)。

在本文中,我们的目标是为在Expedia上搜索和预定酒店的用户创建最佳的酒店推荐。我们将此问题建模为多类别的分类问题,并构建SVM和决策树集成的方法,根据用户的搜索细节,预测用户可能预定酒店的簇(cluster)。

数据

数据是匿名的,几乎所有字段都是数字格式。数据集可以在Kaggle上找到(链接在文末),我们将使用train.csv捕获用户行为的日志,destination.csv包含包含用户对酒店评论的相关信息。

下面的图提供了train.csv的概要:

下面的图提供了destinations.csv的概要:

import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
from sklearn.model_selectionimport cross_val_score
from sklearn.ensembleimport RandomForestClassifier
from sklearn.pipelineimport make_pipeline
from sklearnimport preprocessing
from sklearn.preprocessingimport StandardScaler
from sklearnimport svm

为了能够在本地处理,我们随机抽取样本为记录的1%。然后,我们有241,179条记录。

df= pd.read_csv('train.csv.gz',sep=',')。dropna()
dest= pd.read_csv('destinations.csv.gz')
df= df.sample(frac= 0.01,random_state= 99)
df.shape

(241179,24)

EDA

目标是根据用户搜索中的信息预测用户将预订哪个hotel_cluster。共有100个簇。换句话说,我们正在处理100个类的分类问题。

plt.figure(figsize=(12,6))
sns.distplot(df ['hotel_cluster'])

数据非常好地分布在所有100个簇上,并且数据是偏态的。

特征工程

日期时间,签入日期和签出日期列不能直接使用,我们将从中提取年份和月份。首先,我们定义了几个函数来实现它,我们还定义了一个合并destination.csv的函数。

from datetimeimport datetime
def get_year(x):
    if xis not None and type(x)is not float:
        try:
            return datetime.strptime(x,'%Y-%m-%d').year
        except ValueError:
            return datetime.strptime(x,'%Y-%m-%d %H:%M:%S').year
    else:
        return 2013
    pass
def get_month(x):
    if xis not None and type(x)is not float:
        try:
            return datetime.strptime(x,'%Y-%m-%d').month
        except:
            return datetime.strptime(x,'%Y-%m-%d %H:%M:%S').month
    else:
        return 1
    pass

def left_merge_dataset(left_dframe, right_dframe, merge_column):
    return pd.merge(left_dframe, right_dframe, on=merge_column, how='left')

处理date_time列:

df['date_time_year']= pd.Series(df.date_time, index= df.index)
df['date_time_month']= pd.Series(df.date_time, index= df.index)
from datetimeimport datetime
df.date_time_year= df.date_time_year.apply(lambda x: get_year(x))
df.date_time_month= df.date_time_month.apply(lambda x: get_month(x))
del df['date_time']

处理srch_ci列:

df['srch_ci_year']= pd.Series(df.srch_ci, index=df.index)
df['srch_ci_month']= pd.Series(df.srch_ci, index=df.index)
# convert year & months to int
df.srch_ci_year= df.srch_ci_year.apply(lambda x: get_year(x))
df.srch_ci_month= df.srch_ci_month.apply(lambda x: get_month(x))
# remove the srch_ci column
del df['srch_ci']

处理srch_co列:

df['srch_co_year']= pd.Series(df.srch_co, index=df.index)
df['srch_co_month']= pd.Series(df.srch_co, index=df.index)
# convert year & months to int
df.srch_co_year= df.srch_co_year.apply(lambda x: get_year(x))
df.srch_co_month= df.srch_co_month.apply(lambda x: get_month(x))
# remove the srch_co column
del df['srch_co']

初步分析

在创建新特征并删除无用的特征之后,我们想知道是否有任何与hotel_cluster相关的内容。这可以让我们了解是否应该更加关注某些特定的特征。

df.corr()[ “hotel_cluster”]。sort_values()

没有列与hotel_cluster线性相关,这意味着对特征之间的线性关系建模的方法可能不适合该问题。

策略

经过简单的谷歌搜索,不难发现,对于已知的搜索目的地组合,酒店所在国家,酒店的行情肯定有助于找到酒店簇。我们这样做:

pieces= [df.groupby(['srch_destination_id','hotel_country','hotel_market','hotel_cluster'])['is_booking'].agg(['sum','count'])]
agg= pd.concat(pieces).groupby(level=[0,1,2,3]).sum()
agg.dropna(inplace=True)
agg.head()
agg ['sum_and_cnt']= 0.85 * agg ['sum']+ 0.15 * agg ['count']
agg= agg.groupby(level= [0,1,2])。apply(lambda x:x.astype(float)/x.sum())
agg.reset_index(inplace= True)
agg.head()
agg_pivot= agg.pivot_table(index= ['srch_destination_id','hotel_country','hotel_market'],columns='hotel_cluster',values='sum_and_cnt')。reset_index()
agg_pivot.head()

合并目标表和新创建的聚合数据透视表。

df= pd.merge(df,dest,how='left',on='srch_destination_id')
df= pd.merge(df,agg_pivot,how='left',on= ['srch_destination_id','hotel_country',' hotel_market'])
df.fillna(0,
inplace= True)df.shape

(241179,276)

实现算法

我们只关注预订活动。

df= df.loc [df ['is_booking']== 1]

获取特征和标签。

X= df.drop(['user_id','hotel_cluster','is_booking'], axis=1)
y= df.hotel_cluster

随机森林分类器

我们通过k折交叉验证报告性能度量,而Pipeline可以更轻松地组成估计量。

clf= make_pipeline(preprocessing.StandardScaler(),RandomForestClassifier(n_estimators= 273,max_depth= 10,random_state= 0))
np.mean(cross_val_score(clf,X,y,cv= 10))

0.24865023372782996

SVM分类器

SVM非常耗时。但是,我们取得的成绩更好。

from sklearnimport svm
clf= make_pipeline(preprocessing.StandardScaler(), svm.SVC(decision_function_shape='ovo'))
np.mean(cross_val_score(clf, X, y, cv=10))

0.3228727137315005

Github:https://github.com/susanli2016/Machine-Learning-with-Python/blob/master/Hotel%20recommendation.ipynb

数据集:https://www.kaggle.com/c/expedia-hotel-recommendations/data

本文分享自微信公众号 - ATYUN订阅号(atyun_com),作者:yxy

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 帮助数据科学家理解数据的23个pandas常用代码

    返回给定轴缺失的标签对象,并在那里删除所有缺失数据(’any’:如果存在任何NA值,则删除该行或列。)。

    AiTechYun
  • 如何处理机器学习中类的不平衡问题

    不平衡类使机器学习的“准确性”受到破坏。这在机器学习(特别是分类)中是一个非常普遍的问题,在每个类中都有一个不成比例的数据集。标准的准确性不再可靠地度量性能,这...

    AiTechYun
  • 用Streamlit构建机器学习应用

    Streamlit是一个开放源码的Python库,它可以轻松地为机器学习建模漂亮的应用程序。你可以很容易地通过pip在你的终端上安装它,然后开始用Python编...

    AiTechYun
  • 用 Pandas 进行数据处理系列 二

    获取行操作df.loc[3:6]获取列操作df['rowname']取两列df[['a_name','bname']] ,里面需要是一个 list 不然会报错增...

    zucchiniy
  • Python中字段抽取、字段拆分、记录抽取

    1、字段抽取 字段抽取是根据已知列数据的开始和结束位置,抽取出新的列 字段截取函数:slice(start,stop) 注意:和数据结构的访问方式一样,开始位置...

    Erin
  • 【MathorCup】2020年 A题 无车承运人平台线路定价问题,特征间的相关性分析

    问题 1:通过定量分析的方法,研究影响无车承运人平台进行货运线路定价的主要因素有哪些,并说明理由。 问题 2:根据附件 1 数据,通过建立数学模型,对已经成交...

    不太灵光的程序员
  • Pandas进阶修炼120题,给你深度和广度的船新体验

    本文为你介绍Pandas基础、Pandas数据处理、金融数据处理等方面的一些习题。

    数据派THU
  • Day05| 第四期-电商数据分析

    疫情期间,想必我们会增加网上购物,人们的生活越来越数字化。当我们消费时,无论是线上和线下都会产生大量的交易数据,对于商家来说数字化的运营方式非常必要,从大量的交...

    DataScience
  • Pandas 数据分析: 3 种方法实现一个实用小功能

    与时间相关,自然第一感觉便是转化为datetime格式,这里需要注意:需要首先将两列转化为 str 类型。

    double
  • 使用pandas筛选出指定列值所对应的行

    该方法其实就是找出每一行中符合条件的真值(true value),如找出列A中所有值等于foo

    星星在线

扫码关注云+社区

领取腾讯云代金券