美文网首页
AFM(Attentional Factorization Ma

AFM(Attentional Factorization Ma

作者: Colleen_oh | 来源:发表于2021-05-19 17:04 被阅读0次

    这篇文章主要是对介绍AFM的原理以及跑AFM的源代码。
    《Attentional Factorization Machines:Learning the Weight of Feature Interactions via Attention Networks∗》
    AFM原文:Attentional Factorization Machines: Learning the Weight of Feature Interactions via Attention Networks | IJCAI
    源码已经被大牛整理了:Recommend-System-tf2.0/AFM at master · jc-LeeHub/Recommend-System-tf2.0 · GitHub
    个人整理的源码:AFM-default · andyham/MachineLearning - 码云 - 开源中国 (gitee.com)

    一、介绍&背景

    1.1 摘要

    《Attentional Factorization Machines:Learning the Weight of Feature Interactions via Attention Networks∗》这篇文章主要是说如何通过Attention学习特征之间的相互作用的权重。
    比较白话地说,主要写了FM与Attention的结合,以及FM结合Attention后的效果。主要目的就是通过Attention来学习FM中的交互特征的重要性(权重)。

    1.2 FM缺点以及AMF改进点

    文章中提到,FM模型中,对于不同的特征会有相同的权重,这样不仅无法区分重点和非重要的特征,还会为模型增加不必要的噪声。

    为了解决上面的问题,AMF的提出就是为了区分特征交互的重要性(weight),通过Attention学习特征交互的重要性(weight)。

    1.3 FM

    FM的细节这里就不说了,FM公式如下:


    这里提一下,Wi是一个特征权重,wij是两个特征交互的权重。AFM就是在wij特征交互权重这里下功夫的。

    这里详细根据公式可以看出FM有以下的不足:
    (1)在估计第i个特征所设计的所有特征交互时,共享一个潜在向量Vi。
    (2)所有估计的特征交互Wij的权重都为1。
    (3)所有特征都会计算在内,但显然会存在不重要(无意义)的特征。

    二、 AFM

    下图为AFM的神经网络结构图。


    AFM的结构图

    下面主要从成对交互层和基于Attention的池化层开始介绍AFM

    2.1 可配对的交互层(Pair-wise Interaction Layer)

    FM中交互公式如下:


    通过定义成对交互层,我们可以在神经网络结构下表达FM。
    为了说明这一点,使用一个sum pooling,然后用一个全连接层将其投射到预测分数中。公式如下:


    上面公式中,P^T是预测层的权重,b为误差。
    其实就是基于(2)公式首先进行求和,再与预测权重求积,最后在公式后面增加了b,即误差。

    若P^T=1,b=0,就可以恢复回FM模型的公式了。

    2.2 Attention池化层(Attention-based Pooling Layer)

    基于FM的缺点,建议通过对交互向量进行加权和,对特征向量采用注意力机制(Attention):

    其中aij是特征交互作用wij的注意力评分,体现了wij再预测中的重要性。

    为了解决泛化性问题,用多层感知机(MLP)来确定Attention分数,即Attention network。
    Attention network的输入是两个特征的交互向量,这可在embedding空间中体现交互信息:



    其中T为隐藏层大小(attention factor),W为模型参数,计算aij时会做标准化处理。

    基于Attention的池化层的输出是一个k维向量,它可通过区分重要性来压缩embedding空间中所有特征交互的作用。

    整体AFM模型:

    2.3 计算损失值

    求loss公式如下:


    2.4 效果

    在两个数据集Frappe以及Movielens上都有比较好的提升。


    三、python实现

    3.1 module准备

    tensorflow==2.0.0
    keras==2.4.3
    numpy==1.16.0
    pandas==1.0.3
    scikit-learn==0.19.1
    

    3.2 查看AFM下的数据结构

    > tree
    .
    ├── __init__.py
    ├── __pycache__
    │   ├── layer.cpython-36.pyc
    │   ├── model.cpython-36.pyc
    │   └── utils.cpython-36.pyc
    ├── layer.py
    ├── model.py
    ├── tensorboard
    │   └── events.out.tfevents.1621411918.PS2020GBYFOJBO.16880.5.v2
    ├── train.py
    └── utils.py
    
    2 directories, 9 files
    

    主要是layer.py、model.py、train.py和utils.py这四个代码。可以大牛源码那里下载,也可以直接下载我整理的。

    3.3 执行train.py文件

    数据是在前面源码链接中的Data里面的train.txt。这里是数据是Criteo数据集,前十三列是数值特征(I1-I13),后面的是类别特征(C14-C39)。
    把train.py中的file改了一下,如下:

    file = r'../Data/train.txt'
    

    修改后的train.py如下:

    '''
    # Time   : 2020/12/9 17:28
    # Author : junchaoli
    # File   : train.py
    '''
    
    from model import AFM
    from utils import create_criteo_dataset
    
    import tensorflow as tf
    from tensorflow.keras import optimizers, losses, metrics
    from sklearn.metrics import accuracy_score
    
    if __name__ == '__main__':
        file = r'../Data/train.txt'
        test_size = 0.2
        feature_columns, (X_train, y_train), (X_test, y_test) = \
                            create_criteo_dataset(file, test_size=test_size)
    
        model = AFM(feature_columns, 'att')
        optimizer = optimizers.SGD(0.01)
    
        # dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))
        # dataset = dataset.batch(32).prefetch(tf.data.experimental.AUTOTUNE)
        #
        # model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])
        # model.fit(dataset, epochs=100)
        # pre = model.predict(X_test)
    
        summary = tf.summary.create_file_writer('tensorboard')
        for i in range(100):
            with tf.GradientTape() as tape:
                pre = model(X_train)
                loss = tf.reduce_mean(losses.binary_crossentropy(y_train, pre))
                print(loss.numpy())
            # with summary.as_default():
                # tf.summary.scalar('loss', loss, i)
            grad = tape.gradient(loss, model.variables)
            optimizer.apply_gradients(grads_and_vars=zip(grad, model.variables))
        pre = model(X_test)
    
        pre = [1 if x>0.5 else 0 for x in pre]
        print("Accuracy: ", accuracy_score(y_test, pre))
    

    ps:如果要套其他数据就要从 utils.py中的create_criteo_dataset入手。
    然后就在cmd中python train.py就可以执行成功了。
    结果如下:(省略了一开始的误差)

    ·······
    0.6361494
    0.63559574
    0.635045
    0.6344969
    0.6339517
    0.6334093
    0.63286966
    0.6323327
    0.6317983
    0.6312668
    0.6307378
    0.6302117
    0.6296881
    0.6291671
    Accuracy:  0.81
    

    就是执行一步步把误差给计算出来,然后最后返回Accuracy。准确率是0.81。

    在论文中测试的数据集是Frappe以及Movielens,待更新~~~~~~

    相关文章

      网友评论

          本文标题:AFM(Attentional Factorization Ma

          本文链接:https://www.haomeiwen.com/subject/flkyjltx.html