推荐系统中传统模型——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)


相关推荐

  • 三点估算法怎么计算_比例估算法公式

    三点估算法怎么计算_比例估算法公式某公司接到一栋大楼的布线任务,经过分析决定将大楼的四层布线任务分别交给甲、乙、丙、丁四个项目经理,每人负责一层布线任务,每层面积为10000平米。布线任务由同一个施工队施工,该工程队有5个施工组。甲经过测算,预计每个施工组每天可以铺设完成200平米,于是估计任务完成时间为10天,甲带领施工队最终经过14天完成任务;乙在施工前咨询了工程队中有经验的成员,经过分析之后估算时间为12天,乙带领施工队最终…

    2022年10月30日
  • windows远程桌面,停留在“请稍后”页面[通俗易懂]

    windows远程桌面,停留在“请稍后”页面[通俗易懂]最近登陆局域网远程桌面,输入账号密码,停留在“请稍后”页面,卡半天也进不去。我的解决方法:1.注销其他远程登陆帐户。2.重新连接远程桌面。

    2022年10月24日
  • Winform布局美化样例

    Winform布局美化样例做了好多年Winform的程序的开发,主窗口的界面设计一般都要求做的更好一些,可以根据不同的系统功能模块进行归类整合,能使客户迅速寻找到相关功能的同时,也能感觉到整体性的美观大方,因此主窗口的界面设计总是会精益求精,力求做到更好用、更美观,这样才能吸引客户使用。目前的主体界面设计,可以使用很多控件进行美化,这样能使得开发者能够迅速开发好美观的界面,也可以使得界面总体性有一个统一、规范的基准。一般推

  • 211逆袭浙大-计算机及相关衍生专业保研之路纪实(深度长文,收藏了)

    211逆袭浙大-计算机及相关衍生专业保研之路纪实(深度长文,收藏了)面试过N个院校,最后上岸浙江大学软件学院

  • cglib代理[通俗易懂]

    cglib代理[通俗易懂]cglib代理​ 在此之前,我们学习了JDK动态代理,而JDK动态代理有一定的局限性,因为使用JDK动态代理时,被代理类必须实现接口,然后动态代理生成的代理类同时实现该接口实现代理模式,但在特定情况下没办法让被代理类实现接口,那么此时我们就需要使用cglib代理。代理模式的三要素两个成员:被代理对象、执行者(类似于Spring中切面的概念)使用场景:当某件事情不方便自己做,但是必须要做时…

  • 求两个对角向上、列索引是偶数的元件和。

    求两个对角向上、列索引是偶数的元件和。

发表回复

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

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