推薦系統實踐 0x0e LS-PLM


在之前介紹的幾個模型中,存在這些問題:

  1. LR不能捕捉非線性,只能進行一次的回歸預測
  2. GBDT+LR雖然能夠產生非線性特征組合,但是樹模型不適用於超高維稀疏數據
  3. FM利用二階信息來產生變量之間的相關性,但是無法適應高階組合特征,高階組合容易爆炸

那么,下面介紹的LS-PLM模型一定程度上緩解了這個問題。

LS-PLM

LS-PLM是阿里巴巴曾經主流的推薦模型,這一篇文章就來介紹一下LS-PLM模型的內容。LS-PLM可以看做是對LR模型的自然推廣,它采用的是分而治之的策略。先對樣本分片,然后樣本分片中運用邏輯回歸進行預估。分片的作用是為了能夠讓CTR模型對不同的用戶群體。不同使用場景都具有針對性。先對全量樣本進行聚類,然后在對每個分類實施邏輯回歸。透漏一下,這里阿里巴巴使用的分片聚類的經驗值是12。

論文當中LS-PLM的效果與LR模型效果進行對比,如下圖所示。

優勢

LS-PLM存在三個優勢:

  • 端到端的非線性學習能力。通過足夠的划分區域,LS-PLM可以擬合任何復雜的非線性函數,挖掘數據中的非線性模式,節省大量人工處理樣本和特征工程的過程。
  • 可擴展性。與LR模型類似,LS-PLM可以擴展到大量樣本和高維特征。在這之上設計了一個分布式系統,可以在數百台機器上並行訓練模型。在線產品系統中,每天都會訓練和部署幾十個具有數千萬參數的LS-PLM模型。
  • 稀疏性。模型稀疏性是工業環境下在線服務的一個實際問題。這里展示了采用L1和L2,1正則器的LS-PLM可以實現良好的稀疏性。使得部署更加輕量級,在線推斷效率也更高。

論文基於directional derivatives(方向導數)和quasi-Newton(擬牛頓)方法來解決因為正則項使得目標函數非凸的問題。

數學形式

LS-PLM的數學形式如下面公式所示

\[f(x)=\sum_{i=1}^{m}\pi_i(x)\eta_i(x) \]

首先用聚類函數\(\pi\)對模型進行分類分片,再用LR模型計算樣本在分片中具體的CTR,然后將兩者相乘之后求和。公式中的\(m\)就是分片數,可以較好地平衡模型的擬合能力和推廣能力。當\(m=1\)時就會退化為普通的邏輯回歸。

實際上,LS-PLM采用的softma函數x進行分類,sigmoid函數作為回歸。於是公式變成:

\[f(x)=\sum_{i=1}^{m}\pi_i(x)\eta_i(x)=\sum_{i=1}^{m}\frac{e^{u_ix}}{\sum_{j=1}^{m}e^{u_jx}}\frac{1}{1+e^{-w_ix}} \]

\(\{u_1,...u_m\}\)為聚類函數(分片函數)\(\pi_i\)的參數,\(\{w_1,...w_m\}\)為擬合函數\(\eta_i\)的參數。

優化

由於目標函數中的加入的正則化項\(L_1\),\(L_{2,1}\)都是非平滑函數,所以目標函數也是非平滑的、非凸函數。因為目標函數的負梯度方向並不存在,所以用能夠得到f最小的方向導數的方向b作為負梯度的近似值。這里的推導比較復雜,可以看一下原來論文,之后我盡可能用通俗易懂的語言補充這里。

這個\(L_{2,1}\)挺意思的,貼一下它原來的公式:

\[||\Theta||_{2,1}=L_{2,1}=\sum_{i=1}^d\sqrt{\sum_{j=1}^{2m}\theta_{ij}^{2}} \]

代碼

import torch
import torch.nn as nn
import torch.optim as optim


class LSPLM(nn.Module):
    def __init__(self, m, optimizer, penalty='l2', batch_size=32, epoch=100, learning_rate=0.1, verbose=False):
        super(LSPLM, self).__init__()
        self.m = m
        self.optimizer = optimizer
        self.batch_size = batch_size
        self.epoch = epoch
        self.verbose = verbose
        self.learning_rate = learning_rate
        self.penalty = penalty

        self.softmax = None
        self.logistic = None

        self.loss_fn = nn.BCELoss(reduction='mean')

    def fit(self, X, y):
        if self.softmax is None and self.logistic is None:
            self.softmax = nn.Sequential(
                nn.Linear(X.shape[1], self.m).double(),
                nn.Softmax(dim=1).double()
            )

            self.logistic = nn.Sequential(
                nn.Linear(X.shape[1], self.m, bias=True).double()
                , nn.Sigmoid())

            if self.optimizer == 'Adam':
                self.optimizer = optim.Adam(self.parameters(), lr=self.learning_rate)
            elif self.optimizer == 'SGD':
                self.optimizer = optim.SGD(self.parameters(), lr=self.learning_rate, weight_decay=1e-5, momentum=0.1,
                                           nesterov=True)

        # noinspection DuplicatedCode
        for epoch in range(self.epoch):

            start = 0
            end = start + self.batch_size
            while start < X.shape[0]:

                if end >= X.shape[0]:
                    end = X.shape[0]

                X_batch = torch.from_numpy(X[start:end, :])
                y_batch = torch.from_numpy(y[start:end]).reshape(1, end - start)

                y_batch_pred = self.forward(X_batch).reshape(1, end - start)
                loss = self.loss_fn(y_batch_pred, y_batch)
                loss.backward()
                self.optimizer.step()
                start = end
                end += self.batch_size

            if self.verbose and epoch % (self.epoch / 20) == 0:
                print('EPOCH: %d, loss: %f' % (epoch, loss))
        return self

    def forward(self, X):
        logistic_out = self.logistic(X)
        softmax_out = self.softmax(X)
        combine_out = logistic_out.mul(softmax_out)
        return combine_out.sum(1)

    def predict_proba(self, X):
        X = torch.from_numpy(X)
        return self.forward(X)

    def predict(self, X):
        X = torch.from_numpy(X)
        out = self.forward(X)
        out[out >= 0.5] = 1.0
        out[out < 0.5] = 0.0
        return out

參考

深度學習推薦系統 王喆編著
Learning Piece-wise Linear Models from Large Scale Data for Ad Click Predict
Github:hailingu/MLFM
LS-PLM學習筆記


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM