使用Python实现Softmax Regression

```import numpy as np
import random

feature_data = []
label_data = []
with open(input_file) as f:
feature_tmp = []
feature_tmp.append(1)  # 偏置项
lines = line.strip().split("\t")
for i in range(len(lines) - 1):
feature_tmp.append(float(lines[i]))
label_data.append(int(lines[-1]))
feature_data.append(feature_tmp)
return np.mat(feature_data), np.mat(label_data).T, len(set(label_data))

"""导入测试数据
:param num: 生成的测试样本的个数
:param m: 样本的维数
:return: 生成测试样本
"""
test_dataset = np.mat(np.ones((num, m)))
for i in range(num):
test_dataset[i, 1] = random.random() * 6 - 3  # 随机生成[-3,3]之间的随机数
test_dataset[i, 2] = random.random() * 15  # 随机生成[0,15]之间是的随机数
return test_dataset

def cost(err, label_data):
"""计算损失函数值
:param err: exp的值
:param label_data: 标签的值
:return: sum_cost / m(float):损失函数的值
"""
m = np.shape(err)[0]
sum_cost = 0.0
for i in range(m):
if err[i, label_data[i, 0]] / np.sum(err[i, :]) > 0:
sum_cost -= np.log(err[i, label_data[i, 0]] / np.sum(err[i, :]))
else:
sum_cost -= 0
return sum_cost / m

def gradient_ascent(feature_data, label_data, k, max_cycle, alpha):
"""利用梯度下降法训练Softmax模型
:param feature_data: 特征
:param label_data: 标签
:param k: 类别的个数
:param max_cycle: 最大的迭代次数
:param alpha: 学习率
:return: weights(mat)：权重
"""
m, n = np.shape(feature_data)
weights = np.mat(np.ones((n, k)))  # 权重的初始化
i = 0
while i <= max_cycle:
err = np.exp(feature_data * weights)
if i % 500 == 0:
print("\t-----iter: ", i, ", cost: ", cost(err, label_data))
row_sum = -err.sum(axis=1)
row_sum = row_sum.repeat(k, axis=1)
err = err / row_sum
for x in range(m):
err[x, label_data[x, 0]] += 1
weights = weights + (alpha / m) * feature_data.T * err
i += 1
return weights

def save_weights(file_name, weights):
"""保存最终的模型
:param file_name: 保存的文件名
:param weights: softmax模型
:return:
"""
f_w = open(file_name, "w")
m, n = np.shape(weights)
for i in range(m):
w_tmp = []
for j in range(n):
w_tmp.append(str(weights[i, j]))
f_w.write("\t".join(w_tmp) + "\n")
f_w.close()

"""导入训练好的Softmax模型
:param weights_path: 权重的存储位置
:return: weights(mat)将权重存到矩阵中
m(int)权重的行数
n(int)权重的列数
"""
with open(weights_path) as f:
w = []
w_tmp = []
lines = line.strip().split("\t")
for x in lines:
w_tmp.append(float(x))
w.append(w_tmp)
weights = np.mat(w)
m, n = np.shape(weights)
return weights, m, n

def predict(test_data, weights):
"""利用训练好的Softmax模型对测试数据进行预测
:param test_data: 测试数据的特征
:param weights: 模型的权重
:return: h.argmax(axis=1)所属的类别
"""
h = test_data * weights
return h.argmax(axis=1)  # 获得所属的类别

def save_result(file_name, result):
"""保存最终的预测结果
:param file_name: 保存最终结果的文件名
:param result: 最终的预测结果
:return:
"""
with open(file_name, "w") as f:
m = np.shape(result)[0]
for i in range(m):
f.write(str(result[i, 0]) + "\n")

if __name__ == "__main__":
input_file = "./data/SoftInput.txt"
weights = gradient_ascent(feature, label, k, 10000, 0.4)  # 训练Softmax模型
save_weights("weights", weights)
result = predict(test_data, w)
save_result("result", result)```

使用scikit-learn中的Softmax Regression

softmax和LogisticRegression分别适用于多分类和二分类问题，sklearn将这两者放在一起，只需设置相应的参数即可选择分类器与对应的优化算法，需要注意的是loss function是否收敛。

```from sklearn.linear_model import LogisticRegression

clf = LogisticRegression(multi_class='ovr', solver='sag')
clf.fit(X_train, y_train)
r = clf.score(X_test, y_test)```