成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

天池學(xué)習(xí)記錄——O2O優(yōu)惠券使用預(yù)測(cè)賽題[1]

soasme / 2541人閱讀

摘要:然而隨機(jī)投放的優(yōu)惠券對(duì)多數(shù)用戶(hù)造成無(wú)意義的干擾。下面我們分別對(duì)訓(xùn)練集中的類(lèi)數(shù)據(jù)對(duì)優(yōu)惠券使用的影響進(jìn)行分析。在里有兩種折扣方法代表折扣率表示滿(mǎn)減。這里我們還要將滿(mǎn)減類(lèi)型用式子轉(zhuǎn)換成折扣率。進(jìn)行預(yù)測(cè)計(jì)算平均得到結(jié)果。

賽題說(shuō)明

應(yīng)用背景:以?xún)?yōu)惠券盤(pán)活老用戶(hù)或吸引新客戶(hù)進(jìn)店消費(fèi)是O2O(Online to Offline)的一種重要營(yíng)銷(xiāo)方式。然而隨機(jī)投放的優(yōu)惠券對(duì)多數(shù)用戶(hù)造成無(wú)意義的干擾。對(duì)商家而言,濫發(fā)的優(yōu)惠券可能降低品牌聲譽(yù),同時(shí)難以估算營(yíng)銷(xiāo)成本。而個(gè)性化投放是提高優(yōu)惠券核銷(xiāo)率的重要技術(shù),它可以讓具有一定偏好的消費(fèi)者得到真正的實(shí)惠,同時(shí)賦予商家更強(qiáng)的營(yíng)銷(xiāo)能力。

目標(biāo):根據(jù)提供的O2O場(chǎng)景相關(guān)的豐富數(shù)據(jù),通過(guò)分析建模,精準(zhǔn)預(yù)測(cè)用戶(hù)是否會(huì)在規(guī)定時(shí)間內(nèi)使用相應(yīng)優(yōu)惠券。


數(shù)據(jù)分析

讀取數(shù)據(jù):

我們看到在 offline 訓(xùn)練數(shù)據(jù)集中有以下 7 類(lèi)數(shù)據(jù):
User_id
Merchant_id
Coupon_id
Discount_rate
Distance
Date_received
Date

當(dāng) Coupon_id 為 null 時(shí)表示無(wú)優(yōu)惠券消費(fèi),此時(shí)Discount_rate和Date_received字段無(wú)意義。

具體字段意義請(qǐng)參考賽題鏈接。

根據(jù) Coupon_id 和 Date 是否為 null,可以將數(shù)據(jù)分為四種類(lèi)型:

print("有優(yōu)惠券,購(gòu)買(mǎi)商品條數(shù)", dfoff[(dfoff["Coupon_id"] != "null") & (dfoff["Date"] != "null")].shape[0])
print("無(wú)優(yōu)惠券,購(gòu)買(mǎi)商品條數(shù)", dfoff[(dfoff["Coupon_id"] == "null") & (dfoff["Date"] != "null")].shape[0])
print("有優(yōu)惠券,沒(méi)有購(gòu)買(mǎi)商品條數(shù)", dfoff[(dfoff["Coupon_id"] != "null") & (dfoff["Date"] == "null")].shape[0])
print("無(wú)優(yōu)惠券,也沒(méi)有購(gòu)買(mǎi)商品條數(shù)", dfoff[(dfoff["Coupon_id"] == "null") & (dfoff["Date"] == "null")].shape[0])

得到結(jié)果:

其中,75382 表示用優(yōu)惠券進(jìn)行了消費(fèi)的數(shù)量,即正樣本;977900 表示領(lǐng)取優(yōu)惠券但沒(méi)有使用,這部分優(yōu)惠券就被浪費(fèi)了,即負(fù)樣本;701602 表示沒(méi)有優(yōu)惠券的普通消費(fèi)。

下面我們分別對(duì)訓(xùn)練集中的 7 類(lèi)數(shù)據(jù)對(duì)優(yōu)惠券使用的影響進(jìn)行分析。

1. 優(yōu)惠券和距離

print("Discount_rate 類(lèi)型:",dfoff["Discount_rate"].unique())
print("Distance 類(lèi)型:", dfoff["Distance"].unique())

我們看到輸出的是str類(lèi)型的數(shù)據(jù),需要將它們轉(zhuǎn)換成numeric類(lèi)型。

Discount_rate里有兩種折扣方法:x in [0,1] 代表折扣率;x : y 表示滿(mǎn) x 減 y。這里我們還要將滿(mǎn) x 減 y 類(lèi)型用式子1-y/x轉(zhuǎn)換成折扣率。并建立折扣券相關(guān)的特征 discount_rate, discount_man, discount_jian, discount_type。代碼如下:

# convert Discount_rate and Distance

def getDiscountType(row):
    if row == "null":
        return "null"
    elif ":" in row:
        return 1
    else:
        return 0

def convertRate(row):
    """Convert discount to rate"""
    if row == "null":
        return 1.0
    elif ":" in row:
        rows = row.split(":")
        return 1.0 - float(rows[1])/float(rows[0])
    else:
        return float(row)

def getDiscountMan(row):
    if ":" in row:
        rows = row.split(":")
        return int(rows[0])
    else:
        return 0

def getDiscountJian(row):
    if ":" in row:
        rows = row.split(":")
        return int(rows[1])
    else:
        return 0

def processData(df):
    
    # convert discunt_rate
    df["discount_rate"] = df["Discount_rate"].apply(convertRate)
    df["discount_man"] = df["Discount_rate"].apply(getDiscountMan)
    df["discount_jian"] = df["Discount_rate"].apply(getDiscountJian)
    df["discount_type"] = df["Discount_rate"].apply(getDiscountType)
    print(df["discount_rate"].unique())
    
    # convert distance
    df["distance"] = df["Distance"].replace("null", -1).astype(int)
    print(df["distance"].unique())
    return df

dfoff = processData(dfoff)
dftest = processData(dftest)

2. 時(shí)間
對(duì)收到優(yōu)惠券的日期date_received和消費(fèi)日期date_buy進(jìn)行處理:

date_received = dfoff["Date_received"].unique()
date_received = sorted(date_received[date_received != "null"])

date_buy = dfoff["Date"].unique()
date_buy = sorted(date_buy[date_buy != "null"])

date_buy = sorted(dfoff[dfoff["Date"] != "null"]["Date"])

并輸出結(jié)果:

查看顧客每天收到的優(yōu)惠券數(shù)量:

couponbydate = dfoff[dfoff["Date_received"] != "null"][["Date_received", "Date"]].groupby(["Date_received"], as_index=False).count()
couponbydate.columns = ["Date_received","count"]
couponbydate.head()

查看顧客用這些優(yōu)惠券進(jìn)行了消費(fèi)的數(shù)量:

buybydate = dfoff[(dfoff["Date"] != "null") & (dfoff["Date_received"] != "null")][["Date_received", "Date"]].groupby(["Date_received"], as_index=False).count()
buybydate.columns = ["Date_received","count"]
buybydate.head()

將以上數(shù)據(jù)可視化:

plt.figure(figsize = (12,8))
date_received_dt = pd.to_datetime(date_received, format="%Y%m%d")

plt.subplot(211)
plt.bar(date_received_dt, couponbydate["count"], label = "number of coupon received" )
plt.bar(date_received_dt, buybydate["count"], label = "number of coupon used")
plt.yscale("log")
plt.ylabel("Count")
plt.legend()

plt.subplot(212)
plt.bar(date_received_dt, buybydate["count"]/couponbydate["count"])
plt.ylabel("Ratio(coupon used/coupon received)")
plt.tight_layout()

提取特征

上面顯示的是多帶帶一天的數(shù)據(jù)量,我們知道人們一般在星期天上街比較多,使用優(yōu)惠券的可能性也增大,所以現(xiàn)在我們以星期為依據(jù)新建特征。

def getWeekday(row):
    if row == "null":
        return row
    else:
        return date(int(row[0:4]), int(row[4:6]), int(row[6:8])).weekday() + 1

dfoff["weekday"] = dfoff["Date_received"].astype(str).apply(getWeekday)
dftest["weekday"] = dftest["Date_received"].astype(str).apply(getWeekday)

# weekday_type :  周六和周日為1,工作日為0
dfoff["weekday_type"] = dfoff["weekday"].apply(lambda x : 1 if x in [6,7] else 0 )
dftest["weekday_type"] = dftest["weekday"].apply(lambda x : 1 if x in [6,7] else 0 )

# change weekday to one-hot encoding 
weekdaycols = ["weekday_" + str(i) for i in range(1,8)]
print(weekdaycols)

tmpdf = pd.get_dummies(dfoff["weekday"].replace("null", np.nan))
tmpdf.columns = weekdaycols
dfoff[weekdaycols] = tmpdf

tmpdf = pd.get_dummies(dftest["weekday"].replace("null", np.nan))
tmpdf.columns = weekdaycols
dftest[weekdaycols] = tmpdf

得到的tmpdf為以下形式:

對(duì)["date_received"]數(shù)據(jù)進(jìn)行標(biāo)注,轉(zhuǎn)換成numeric

def label(row):
    if row["Date_received"] == "null":
        return -1
    if row["Date"] != "null":
        td = pd.to_datetime(row["Date"], format="%Y%m%d") -  pd.to_datetime(row["Date_received"], format="%Y%m%d")
        if td <= pd.Timedelta(15, "D"):
            return 1
    return 0
dfoff["label"] = dfoff.apply(label, axis = 1)

若 Date_received == "null",則 y = -1;Date != "null" & Date-Date_received <= 15,則 y = 1;否則,y = 0。

此時(shí),這些轉(zhuǎn)換后的數(shù)據(jù)已經(jīng)以0,1,-1的形式存在了label列中。

模型訓(xùn)練

在應(yīng)用模型前,首先對(duì)數(shù)據(jù)進(jìn)行劃分。在這里,我們將 20160101 到 20160515 的數(shù)據(jù)用作訓(xùn)練集(train),20160516 到 20160615 的數(shù)據(jù)用作驗(yàn)證集(valid)。

df = dfoff[dfoff["label"] != -1].copy()
train = df[(df["Date_received"] < "20160516")].copy()
valid = df[(df["Date_received"] >= "20160516") & (df["Date_received"] <= "20160615")].copy()
print(train["label"].value_counts())
print(valid["label"].value_counts())

用線(xiàn)性模型 SGDClassifier 進(jìn)行預(yù)測(cè)。

predictors = original_feature
print(predictors)

def check_model(data, predictors):
    
    classifier = lambda: SGDClassifier(
        loss="log", 
        penalty="elasticnet", 
        fit_intercept=True, 
        max_iter=100, 
        shuffle=True, 
        n_jobs=1,
        class_weight=None)

    model = Pipeline(steps=[
        ("ss", StandardScaler()),
        ("en", classifier())
    ])

    parameters = {
        "en__alpha": [ 0.001, 0.01, 0.1],
        "en__l1_ratio": [ 0.001, 0.01, 0.1]
    }

    folder = StratifiedKFold(n_splits=3, shuffle=True)
    
    grid_search = GridSearchCV(
        model, 
        parameters, 
        cv=folder, 
        n_jobs=-1, 
        verbose=1)
    grid_search = grid_search.fit(data[predictors], 
                                  data["label"])
    
    return grid_search

if not os.path.isfile("1_model.pkl"):
    model = check_model(train, predictors)
    print(model.best_score_)
    print(model.best_params_)
    with open("1_model.pkl", "wb") as f:
        pickle.dump(model, f)
else:
    with open("1_model.pkl", "rb") as f:
        model = pickle.load(f)

接下來(lái),對(duì)每個(gè)優(yōu)惠券預(yù)測(cè)的結(jié)果計(jì)算 AUC,再對(duì)所有的取平均。計(jì)算 AUC 的時(shí)候,如果label只有一類(lèi),就直接跳過(guò),因?yàn)?AUC 無(wú)法計(jì)算。

進(jìn)行預(yù)測(cè):

y_valid_pred = model.predict_proba(valid[predictors])
valid1 = valid.copy()
valid1["pred_prob"] = y_valid_pred[:, 1]

計(jì)算平均 AUC:

vg = valid1.groupby(["Coupon_id"])
aucs = []
for i in vg:
    tmpdf = i[1] 
    if len(tmpdf["label"].unique()) != 2:
        continue
    fpr, tpr, thresholds = roc_curve(tmpdf["label"], tmpdf["pred_prob"], pos_label=1)
    aucs.append(auc(fpr, tpr))
print(np.average(aucs))

得到結(jié)果0.5348655160896371

對(duì)測(cè)試集進(jìn)行預(yù)測(cè)并提交結(jié)果:

y_test_pred = model.predict_proba(dftest[predictors])
dftest1 = dftest[["User_id","Coupon_id","Date_received"]].copy()
dftest1["label"] = y_test_pred[:,1]
dftest1.to_csv("submit1.csv", index=False, header=False)

至此,我們已經(jīng)得到一個(gè)提交結(jié)果,在這個(gè)過(guò)程中用到的特征是優(yōu)惠券,距離和時(shí)間。預(yù)測(cè)效果較差,還需要進(jìn)行進(jìn)一步的特征工程,來(lái)得到更好的效果。

思路解答

總結(jié)以上思路,首先對(duì)數(shù)據(jù)進(jìn)行分析,通過(guò)畫(huà)圖可以更直觀的反映出數(shù)據(jù)的特征;然后根據(jù)對(duì)數(shù)據(jù)對(duì)分析結(jié)果,進(jìn)行特征提取,用這些特征訓(xùn)練所用的模型。在訓(xùn)練過(guò)程中通過(guò)劃分?jǐn)?shù)據(jù)集,分為訓(xùn)練集和驗(yàn)證集兩部分,對(duì)模型進(jìn)行訓(xùn)練;最后,將測(cè)試集的數(shù)據(jù)喂給訓(xùn)練好的模型,得到預(yù)測(cè)結(jié)果,并轉(zhuǎn)換為能提交的.csv格式的文件。

這就是進(jìn)行一次數(shù)據(jù)分析的大致思路,就本題來(lái)說(shuō),在特征工程和模型的選擇上還有更多的思考余地,來(lái)提高準(zhǔn)確率。

用到的知識(shí)點(diǎn)

one-hot encoding
AUC

遇到的問(wèn)題

針對(duì)博主的學(xué)習(xí),在這次的賽題總結(jié)中反映出的問(wèn)題有以下 3 點(diǎn):

數(shù)據(jù)可視化的代碼部分,不夠了解,而畫(huà)圖可能為我們提供很多思路

對(duì)各個(gè)模型的參數(shù)有哪些需要深入了解,如果不想做調(diào)包俠客,就更要掌握調(diào)參背后的原理

特征工程是制勝的關(guān)鍵,需要不斷的練習(xí)學(xué)習(xí)

參考鏈接:
https://tianchi.aliyun.com/no...
https://tianchi.aliyun.com/no...


不足之處,歡迎指正。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41879.html

相關(guān)文章

  • 天池大數(shù)據(jù)比賽總結(jié)

    摘要:這次比賽的題目是給定年月份的用戶(hù)在不同地點(diǎn)口碑購(gòu)買(mǎi)記錄,以及年月淘寶上用戶(hù)的購(gòu)物行為數(shù)據(jù),來(lái)預(yù)測(cè)月這一整月用戶(hù)來(lái)到一個(gè)地點(diǎn)之后會(huì)光顧哪些口碑商鋪。 一直想總結(jié)一下這次的比賽,拖啊拖。。。一直等到現(xiàn)在,趁著現(xiàn)在要找實(shí)習(xí),好好總結(jié)一下。 比賽題目 比賽的官方網(wǎng)站在這,IJCAI SocInf16。 這次比賽的題目是給定 2015 年 7 ~ 11 月份的用戶(hù)在不同地點(diǎn)口碑購(gòu)買(mǎi)記錄,以及 2...

    printempw 評(píng)論0 收藏0
  • 人工智能/數(shù)據(jù)科學(xué)比賽匯總 2019.2

    摘要:內(nèi)容來(lái)自,人工智能數(shù)據(jù)科學(xué)比賽整理平臺(tái)。消費(fèi)者人群畫(huà)像信用智能評(píng)分月日月中國(guó)移動(dòng)福建公司提供年月份的樣本數(shù)據(jù)脫敏,包括客戶(hù)的各類(lèi)通信支出欠費(fèi)情況出行情況消費(fèi)場(chǎng)所社交個(gè)人興趣等豐富的多維度數(shù)據(jù)。 內(nèi)容來(lái)自 DataSciComp,人工智能/數(shù)據(jù)科學(xué)比賽整理平臺(tái)。Github:iphysresearch/DataSciComp 本項(xiàng)目由 ApacheCN 強(qiáng)力支持。 微博 | 知乎 | C...

    twohappy 評(píng)論0 收藏0
  • 人工智能/數(shù)據(jù)科學(xué)比賽匯總 2019.3

    摘要:內(nèi)容來(lái)自,人工智能數(shù)據(jù)科學(xué)比賽整理平臺(tái)。本項(xiàng)目由強(qiáng)力支持。天池閱讀更多 內(nèi)容來(lái)自 DataSciComp,人工智能/數(shù)據(jù)科學(xué)比賽整理平臺(tái)。Github:iphysresearch/DataSciComp 本項(xiàng)目由 ApacheCN 強(qiáng)力支持。 微博 | 知乎 | CSDN | 簡(jiǎn)書(shū) | OSChina | 博客園 全球城市計(jì)算AI挑戰(zhàn)賽 3月19日 - 4月11日, 2019 // ...

    mayaohua 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<