推荐系统中传统模型——LightGBM + FFM融合

推荐系统中传统模型——LightGBM + FFM融合之前比较相关的文章:推荐系统中传统模型——LightGBM+LR融合python-机器学习lightgbm相关实践1深入FFM原理与实践来自美团技术团队的,深入FFM原理与实践FM和FFM模型是最近几年提出的模型,凭借其在数据量比较大并且特征稀疏的情况下,仍然能够得到优秀的性能和效果的特性,屡次在各大公司举办的CTR预估比赛中获得不错的战绩。美团技术团队在搭建DSP的过程中,探索并使用了FM和FFM模型进行CTR和CVR预估,并且取得了不错的效果。经过One-Hot编码之后,大部分

大家好,又见面了,我是你们的朋友全栈君。

之前比较相关的文章:
推荐系统中传统模型——LightGBM + LR融合
python – 机器学习lightgbm相关实践


1 深入FFM原理与实践

来自美团技术团队的,深入FFM原理与实践

FM和FFM模型是最近几年提出的模型,凭借其在数据量比较大并且特征稀疏的情况下,仍然能够得到优秀的性能和效果的特性,屡次在各大公司举办的CTR预估比赛中获得不错的战绩。美团技术团队在搭建DSP的过程中,探索并使用了FM和FFM模型进行CTR和CVR预估,并且取得了不错的效果。

  • 经过One-Hot编码之后,大部分样本数据特征是比较稀疏的。
  • One-Hot编码的另一个特点就是导致特征空间大。

同时通过观察大量的样本数据可以发现,某些特征经过关联之后,与label之间的相关性就会提高。
FFM主要用来预估站内的CTR和CVR,即一个用户对一个商品的潜在点击率和点击后的转化率。

CTR和CVR预估模型都是在线下训练,然后用于线上预测。两个模型采用的特征大同小异,主要有三类:用户相关的特征、商品相关的特征、以及用户-商品匹配特征。用户相关的特征包括年龄、性别、职业、兴趣、品类偏好、浏览/购买品类等基本信息,以及用户近期点击量、购买量、消费额等统计信息。商品相关的特征包括所属品类、销量、价格、评分、历史CTR/CVR等信息。用户-商品匹配特征主要有浏览/购买品类匹配、浏览/购买商家匹配、兴趣偏好匹配等几个维度。

为了使用FFM方法,所有的特征必须转换成“field_id:feat_id:value”格式,
field_id代表特征所属field的编号,feat_id是特征编号,value是特征的值

数值型的特征比较容易处理,只需分配单独的field编号,如用户评论得分、商品的历史CTR/CVR等。categorical特征需要经过One-Hot编码成数值型,编码产生的所有特征同属于一个field,而特征的值只能是0或1,如用户的性别、年龄段,商品的品类id等。除此之外,还有第三类特征,如用户浏览/购买品类,有多个品类id且用一个数值衡量用户浏览或购买每个品类商品的数量。这类特征按照categorical特征处理,不同的只是特征的值不是0或1,而是代表用户浏览或购买数量的数值。按前述方法得到field_id之后,再对转换后特征顺序编号,得到feat_id,特征的值也可以按照之前的方法获得。

2 案例

代码案例参考的是:wangru8080/gbdt-lr

其中FFM使用的是libffm库来训练,代码仅给出了构造数据输入的方法(FFMFormat),构造好输入格式后,直接使用libFFM训练即可。

这边libffm所需要的训练格式比较特别:

label field_id:feature_id:value field_id:feature_id:value field_id:feature_id:value …

  • field_id表示每一个特征域的id号
  • feature_id表示所有特征值的id号(可采用连续编码以及hash编码)
  • value:当特征域不是连续特征时,value=1,若为连续特征,value=该特征的值

对于pandas DataFrame格式数据来说:

label  category_feature  continuous_feature  vector_feature
=====  ================  ==================  ==============
0           x               1.1               1 2
1           y               1.2               3 4 5   
0           x               2.2               6 7 8 9

本文仅有category_feature,continuous_feature,vector_feature。

wangru8080/gbdt-lr中,数据转化的代码为:

def FFMFormat(df, label, path, train_len, category_feature = [], continuous_feature = []):
    index = df.shape[0]
    train = open(path + 'train.ffm', 'w')
    test = open(path + 'test.ffm', 'w')
    feature_index = 0
    feat_index = {}
    for i in range(index):
        feats = []
        field_index = 0
        for j, feat in enumerate(category_feature):
            t = feat + '_' + str(df[feat][i])
            if t not in  feat_index.keys():
                feat_index[t] = feature_index
                feature_index = feature_index + 1
            feats.append('%s:%s:%s' % (field_index, feat_index[t], 1))
            field_index = field_index + 1

        for j, feat in enumerate(continuous_feature):
            feats.append('%s:%s:%s' % (field_index, feature_index, df[feat][i]))
            feature_index = feature_index + 1
            field_index = field_index + 1

        print('%s %s' % (df[label][i], ' '.join(feats)))

        if i < train_len:
            train.write('%s %s\n' % (df[label][i], ' '.join(feats)))
        else:
            test.write('%s\n' % (' '.join(feats)))
    train.close()
    test.close()

其中LightGBM 之后的叶子节点数据是离散的数据,

3 Kaggle: Pandas to libffm

网址:https://www.kaggle.com/mpearmain/pandas-to-libffm

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
from sklearn.datasets import make_classification

'''
Another CTR comp and so i suspect libffm will play its part, after all it is an atomic bomb for this kind of stuff.
A sci-kit learn inspired script to convert pandas dataframes into libFFM style data.

The script is fairly hacky (hey thats Kaggle) and takes a little while to run a huge dataset.
The key to using this class is setting up the features dtypes correctly for output (ammend transform to suit your needs)

Example below

'''


class FFMFormatPandas:
    def __init__(self):
        self.field_index_ = None
        self.feature_index_ = None
        self.y = None

    def fit(self, df, y=None):
        self.y = y
        df_ffm = df[df.columns.difference([self.y])]
        if self.field_index_ is None:
            self.field_index_ = {col: i for i, col in enumerate(df_ffm)}

        if self.feature_index_ is not None:
            last_idx = max(list(self.feature_index_.values()))

        if self.feature_index_ is None:
            self.feature_index_ = dict()
            last_idx = 0

        for col in df.columns:
            vals = df[col].unique()
            for val in vals:
                if pd.isnull(val):
                    continue
                name = '{}_{}'.format(col, val)
                if name not in self.feature_index_:
                    self.feature_index_[name] = last_idx
                    last_idx += 1
            self.feature_index_[col] = last_idx
            last_idx += 1
        return self

    def fit_transform(self, df, y=None):
        self.fit(df, y)
        return self.transform(df)

    def transform_row_(self, row, t):
        ffm = []
        if self.y != None:
            ffm.append(str(row.loc[row.index == self.y][0]))
        if self.y is None:
            ffm.append(str(0))

        for col, val in row.loc[row.index != self.y].to_dict().items():
            col_type = t[col]
            name = '{}_{}'.format(col, val)
            if col_type.kind ==  'O':
                ffm.append('{}:{}:1'.format(self.field_index_[col], self.feature_index_[name]))
            elif col_type.kind == 'i':
                ffm.append('{}:{}:{}'.format(self.field_index_[col], self.feature_index_[col], val))
        return ' '.join(ffm)

    def transform(self, df):
        t = df.dtypes.to_dict()
        return pd.Series({idx: self.transform_row_(row, t) for idx, row in df.iterrows()})

########################### Lets build some data and test ############################
### 


train, y = make_classification(n_samples=100, n_features=5, n_informative=2, n_redundant=2, n_classes=2, random_state=42)

train=pd.DataFrame(train, columns=['int1','int2','int3','s1','s2'])
train['int1'] = train['int1'].map(int)
train['int2'] = train['int2'].map(int)
train['int3'] = train['int3'].map(int)
train['s1'] = round(np.log(abs(train['s1'] +1 ))).map(str)
train['s2'] = round(np.log(abs(train['s2'] +1 ))).map(str)
train['clicked'] = y


ffm_train = FFMFormatPandas()
ffm_train_data = ffm_train.fit_transform(train, y='clicked')
print('Base data')
print(train[0:10])
print('FFM data')
print(ffm_train_data[0:10])
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/140641.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 10240

    10240一个特殊的日子

  • linux抓包命令tcpdump保存到wireshark_tcpdump抓包命令举例

    linux抓包命令tcpdump保存到wireshark_tcpdump抓包命令举例一,tcpdump-ilo-s0-n-nn-w/tmp/12345.pcaptcpandport12345注:tcpdump:抓包命令-ilo:抓取lo网卡的数据包(回环网口的包)-s0:从每个分组中读取最开始的snaplen个字节,后面可以跟数字指定截取多少个字节,0是指截取所有。(防止包截断)-nnn:以数字显示主机及端口,不解析主机名…

  • Oracle 字符串拼接「建议收藏」

    Oracle 字符串拼接「建议收藏」有两种方式1、’xx’||’xx’||’aaa’selectidname||’,’||sex||’,’||ageastextfromuser效果id text adad1231asdas 张三,男,23 2、concat()函数注意:oracle只支持两个参数,如果要进行多个字符串的拼接,可以使用多个concat()函数嵌套使用例:如果要实现例1的效果:selectidconcat(name,con

  • phpstrom 2021.12激活吗(JetBrains全家桶)「建议收藏」

    (phpstrom 2021.12激活吗)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1435QFILVV-eyJsaWNlb…

  • Lefse本地运行并更换颜色

    Lefse本地运行并更换颜色首先是lefse的安装由于lefse使用的环境比较早,建议使用conda虚拟环境的方式安装,可以省掉不少麻烦condacreate-nlefsepython=2.7python=2.7#python这里选成2.7否则会卡住环境安装完成后,进入环境安装lefsesourceactivatelefsecondainstalllefse…

  • maven环境变量配置详细步骤(win10)

    maven环境变量配置详细步骤(win10)一、前言最近更新了系统,maven也想了想也需要装个新版本了,去下载了新版本,记录下maven的安装配置,初学小伙伴可以看看。安装前确认已经安装好了JDK,没有安装或下载的小伙伴可以参考我另外一篇文章原创jdk1.8下载与安装教程(win10),其它版本类似。安文件大家可以自己去官网下载,也可以直接在下面到我的网盘下载,官网向来下载速度都比较慢。目前版本是3.6.3版本,有新版本我也…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号