【推荐算法 学习与复现】-- 逻辑回归算法族 -- GBDT+LR

  协同过滤仅仅使用有限的用户行为信息,逻辑回归算法模型大多引入用户行为、用户特征、物品特征和上下文特征等,从CF逐步过渡到综合不同特征的机器学习模型。

(1)逻辑回归模型

        将用户特征(年龄、性别等)、用户行为(收藏、浏览等)、物品特征(属性、描述等)和上下文特征(当前时间、地点等)转化成数值型特征向量;以点击率为优化目标;利用已有数据进行训练学习模型参数;利用学习完成的模型进行推理预测用户点击率。

y=sigmoid(x^Tw)

(2)POLY2模型--特征交叉的开始

        防止“辛普森悖论”(数据在分组研究与总体研究时产生的结论可能是相悖的),改造逻辑回归模型,使其具备特征交叉能力。但是人工难以设计最优特征组合,POLY2采用暴力组合方式。

POLY(w,x)=w_0+\sum_{i=1}^nw_ix_i+\sum_{j_1=1}^{n-1}\sum_{j_2=j_1+1}^nw_{h(j_1,j_2)}x_{j_1}x_{j_2}

但是无差别的特征交叉使得原本稀疏的特征变得更加稀疏,权重参数量级也由 n 上升到 n^2

(3)FM模型 -- 隐向量特征交叉

        将交叉特征权重换成隐向量内积形式,减少参数稀疏性和计算复杂度

POLY(w,x)=w_0+\sum_{i=1}^nw_ix_i+\sum_{j_1=1}^{n-1}\sum_{j_2=j_1+1}^n(w_{j_1}w_{j_2})x_{j_1}x_{j_2}

(4) FFM模型 -- 引入特征域的概念

FFF在模型训练过程中,需要学习 n 个特征在 f 个域上的 k 维隐向量,使每个特征在与不同域的特征交叉时采用不同的隐向量

POLY(w,x)=\sum_{j_1=1}^{n-1}\sum_{j_2=j_1+1}^n(w_{j_1,f_2}*w_{j_2,f_1})x_{j_1}x_{j_2}

(5) GBDT+LR -- 特征工程模型化的开端

        LR模型将推荐问题转换为CTR预测分类问题,但是特征工程构建复杂,特征交叉方式也仅能做到二阶(提高交叉维度会产生组合爆炸问题);GBDT进行特征筛选与组合,生成新的离散特征向量;将生成特征(concatenate到原始特征)作为LR模型输入特征。

  • 引入GBDT,但是树模型不适应高维离散特征
    • 树模型的正则项一般为深度和叶子节点数
    • LR模型对参数W进行正则化,约束了w不可能过大,即不会聚焦个别特征
    • 针对高位离散特征,树模型很有可能根据训练集某些个别特征巧合的实现数据划分

     

代码复现:(大多参考附录2实现,感谢)

数据下载链接:

criteo数据用于推荐系统学习-深度学习文档类资源-CSDN文库icon-default.png?t=M3C8https://download.csdn.net/download/Big_Huang/85155340

import lightgbm as lgb
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

df_data = pd.read_csv('./criteo/train.csv', sep=',')
df_data.drop(['Id'], axis=1, inplace=True)
df_data.fillna(-1, inplace=True)

continuous_fea = ['I'+str(i+1) for i in range(13)]
category_fea = ['C'+str(i+1) for i in range(26)]

# 离散特征one-hot编码
for col in category_fea:
    onehot_feats = pd.get_dummies(df_data[col], prefix=col)
    df_data.drop([col], axis=1, inplace=True)
    df_data = pd.concat([df_data, onehot_feats], axis=1)

label = df_data.pop('Label')
# 划分数据集
x_train, x_val, y_train, y_val = train_test_split(df_data, label, test_size=0.2, random_state=28)

gbm = lgb.LGBMRegressor(objective='binary',
                            subsample= 0.8,
                            min_child_weight= 0.5,
                            colsample_bytree= 0.7,
                            num_leaves=100,
                            max_depth = 12,
                            learning_rate=0.05,
                            n_estimators=10,
                            )

gbm.fit(x_train, y_train,
        eval_set = [(x_train, y_train), (x_val, y_val)],
        eval_names = ['train', 'val'],
        eval_metric = 'binary_logloss',
        # early_stopping_rounds = 100,
        )

model = gbm.booster_            # 获取到建立的树

# 每个样本落在每个树的位置 , 下面两个是矩阵  (样本个数, 树的棵树)  , 每一个数字代表某个样本落在了某个数的哪个叶子节点
gbdt_feats_train = model.predict(df_data, pred_leaf = True)


# 把上面的矩阵转成新的样本-特征的形式, 与原有的数据集合并
gbdt_feats_name = ['gbdt_leaf_' + str(i) for i in range(gbdt_feats_train.shape[1])]
df_train_gbdt_feats = pd.DataFrame(gbdt_feats_train, columns = gbdt_feats_name) 

# 构造新数据集
train = pd.concat([df_data, df_train_gbdt_feats], axis = 1)


from sklearn.preprocessing import MinMaxScaler
# 连续特征归一化
scaler = MinMaxScaler()
for col in continuous_fea:
    train[col] = scaler.fit_transform(train[col].values.reshape(-1, 1))

# 新数据的新特征进行读入编码
for col in gbdt_feats_name:
    onehot_feats = pd.get_dummies(train[col], prefix = col)
    train.drop([col], axis = 1, inplace = True)
    train = pd.concat([train, onehot_feats], axis = 1)


x_train, x_val, y_train, y_val = train_test_split(train, label, test_size = 0.3, random_state = 28)

# 训练逻辑回归模型
lr = LogisticRegression()
lr.fit(x_train, y_train)

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import roc_auc_score
def eval_model(y_pred, y_true):
    print(f"accuracy_score = {accuracy_score(y_true, y_pred)}")
    print(f"precision_score = {precision_score(y_true, y_pred)}")
    print(f"recall_score = {recall_score(y_true, y_pred)}")
    print(f"f1_score = {f1_score(y_true, y_pred)}")
    print(f"auc = {roc_auc_score(y_true, y_pred)}")

pred = [1 if x >= 0.5 else 0 for x in lr.predict_proba(x_val)[:, 1]]
eval_model(pred, np.array(y_val))

 参考:

1. 《深度学习推荐系统》

2. https://datawhalechina.github.io/fun-rec/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值