推荐算法|FM模型预测多分类python实现

2021-12-06 15:39:31 浏览数 (1)

导读:上一期推荐算法|FM模型预测多分类原理简介中介绍了FM进行多分类预测的原理,这一篇我们就来看下如何通过python实现。

1

softmax溢出

因为softmax函数中存在指数运算,而计算机中存储数据是有长度限制的,因此,如果数据过大或者过小就会出现上/下溢出,即exp(1000)=inf,导致我们训练不出结果。

通过上图可发现,softmax不受偏移影响,因此我们把softmax(x)变为softmax(x-z),其中z为x中的最大值,便可同时解决上、下溢出问题。

2

python实现

我们使用鸢尾花数据进行展示,完整代码如下。

代码语言:javascript复制
class Softmax:
    '''
    digits:x变量,dataframe类型
    labels:y标签,dataframe类型,取值为0,1,2...表示不同类别
    '''
    def softmax(self, X):   #softmax函数
        m_max = np.max(X)
        return np.exp(X-m_max) / np.sum(np.exp(X-m_max))#防止溢出
#         return np.exp(X) / np.sum(np.exp(X))
    
    def FM_train(self, digits, labels, maxIter = 100, alpha = 0.01,k = 10):
        
        n, m = np.shape(digits) #样本数和特征数
        c = labels.drop_duplicates().shape[0] #分类的类别数
    
        #1、初始化参数
        self.w = np.zeros(( m,c))
        self.v = normalvariate(0, 0.2) * np.ones((c, m, k))
        self.w_0 = np.zeros((1,c))
        #2、迭代更新
        for iter in range(maxIter):
            for i in range(n):
                x = digits.iloc[i,:]
                y = np.zeros(c)
                y[labels.iloc[i,0]] = 1
                inter_1 = np.dot(x,self.v)
                inter_2 = np.dot(np.multiply(x, x),np.multiply(self.v, self.v))
                #完成交叉项
                interaction = np.sum((np.multiply(inter_1, inter_1) - inter_2),axis=1) / 2.  
                s = self.w_0 np.dot(x,self.w)   interaction  
                p = self.softmax(s)
                #w0更新
                self.w_0 -= alpha * (p - y)
                for z in range(m):   
                    if x[z] != 0:
                        #w更新
                        self.w[z] -= (alpha * (x[z]*(p - y)))[0]
                        for j in range(k):
                            #v更新
                            self.v[:, z, j] -= alpha * (x[z] * inter_1[:,j] - self.v[:, z, j] * x[z] * x[z])*(p-y)[0]
        print(self.w_0)
        return self.w_0,self.w,self.v
    
    def Assessment(self, digits, classLabels):
        n, m = shape(digits)
        allItem = 0
        error = 0
        result = []
        for i in range(n):
            allItem  = 1
            x = digits.iloc[i,:]
            inter_1 = np.dot(x,self.v)
            inter_2 = np.dot(np.multiply(x, x),np.multiply(self.v, self.v))
            interaction = np.sum((np.multiply(inter_1, inter_1) - inter_2),axis=1)
            s = self.w_0 np.dot(x,self.w)   interaction 
            p = self.softmax(s)
            pre = np.argmax(p)#返回最大值
            result.append(pre)
            if pre != classLabels.iloc[i,0] :
                error  = 1
            else:
                continue
        return result,float(error) / allItem

往期推荐:

推荐算法概述

推荐算法|矩阵分解模型

0 人点赞