导读:上一期推荐算法|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
往期推荐:
推荐算法概述
推荐算法|矩阵分解模型