人工智能中文网
  • 主页
  • 线代考研视频
  • 线性代数
  • Python机器学习与算法
  • 大数据与机器学习
  • Python基础入门教程
  • 人工智能中文网
    教程目录
    阅读:

    softmax回归算法实践(softmax分类器Python实现)

    有了前面的理论储备,我们利用上述实现好的函数,构建 Softmax Regression 分类器。在训练分类器的过程中,我们使用如图 1 所示的多分类数据作为训练数据:


    图 1 多分类数据

    利用 Softmax Regression 算法对其进行分类的过程中,主要有两个部分:
    • 利用训练数据对模型进行训练;
    • 对新的数据进行预测;

    对Softmax Regression算法的模型进行训练

    首先,我们利用训练样本训练模型,为了使得 Python 能够支持中文的注释和利用 numpy,我们需要在训练文件“softmax_regression_train.py”的开始加入:
    #codeing:UTF-8
    import numpy as np
    模型训练的主函数如下所示:
    if __name__ == "__main__":
        inputfile = "SoftInput.txt"
        # 1、导入训练数据
        print "---------- 1.load data ------------"
        feature, label, k = load_data(inputfile)
        # 2、训练Softmax模型
        print "---------- 2.training ------------"
        weights = gradientAscent(feature, label, k, 10000, 0.4)
        # 3、保存最终的模型
        print "---------- 3.save model ------------"
        save_model("weights", weights)
    在此主函数中,首先需要导入训练数据,然后便可以利用梯度下降法对模型进行训练。当模型训练结束后,将最终的模型参数保存到文件 weights 中,如程序中所示。

    其中,导入训练数据的 load_data 函数如下所示:
    def load_data(inputfile):
        '''导入训练数据
        input:  inputfile(string)训练样本的位置
        output: feature_data(mat)特征
                label_data(mat)标签
                k(int)类别的个数
        '''
        f = open(inputfile)  # 打开文件
        feature_data = []
        label_data = []
        for line in f.readlines():
            feature_tmp = []
            feature_tmp.append(1)  # 偏置项
            lines = line.strip().split("	")
            for i in xrange(len(lines) - 1):
                feature_tmp.append(float(lines[i]))
            label_data.append(int(lines[-1]))
           
            feature_data.append(feature_tmp)
        f.close()  # 关闭文件
        return np.mat(feature_data), np.mat(label_data).T, len(set(label_data))
    函数 load_data 的输入为训练样本的文件名,通过解析输出训练数据的特征 feature_data、标签 label_data 和训练样本的类别个数 k。

    保存 softmax 模型的 save_model 函数的实现为:
    def save_model(file_name, weights):
        '''保存最终的模型
        input:  file_name(string):保存的文件名
                weights(mat):softmax模型
        '''
        f_w = open(file_name, "w")
        m, n = np.shape(weights)
        for i in xrange(m):
            w_tmp = []
            for j in xrange(n):
                w_tmp.append(str(weights[i, j]))
            f_w.write("	".join(w_tmp) + "
    ")
        f_w.close()
    函数 save_model 将训练好的 Softmax 模型保存到对应的文件中,其中,save_model 函数的输入是保存的文件名 file_name 和对应的 Softmax 模型 weights。

    最终的模型

    训练的具体为:


    通过训练,得到了最终的模型的参数,模型的参数保存在文件 weights 中,其中参数为:

    对新的数据的预测

    对于分类算法而言,训练好的模型需要能够对新的数据集进行划分。利用上述步骤,我们训练好 Softmax Regression 模型,并将其保存在“weights”文件中,此时,我们需要利用训练好的 Softmax Regression 模型对新数据进行预测,同样,为了能够使用 numpy 中的函数和对中文注释的支持,在文件“softmax_regression_test.py”文件开始,我们加入:
    #codeing:UTF-8
    import numpy as np
    测试的主程序如下所示:
    if __name__ == "__main__":
        # 1、导入Softmax模型
        print "---------- 1.load model ------------"
        w, m , n = load_weights("weights")
        # 2、导入测试数据
        print "---------- 2.load data ------------"
        test_data = load_data(4000, m)
        # 3、利用训练好的Softmax模型对测试数据进行预测
        print "---------- 3.get Prediction ------------"
        result = predict(test_data, w)
        # 4、保存最终的预测结果
        print "---------- 4.save prediction ------------"
        save_result("result", result)
    程序中,首先是导入模型的参数,同时需要导入测试的数据,然后利用训练好的 Softmax 模型对测试数据进行预测,最后得到最终的预测结果,并将其保存到文件 result 中。

    其中,load_weights 函数的具体实现如下所示。
    def load_weights(weights_path):
        '''导入训练好的Softmax模型
        input:  weights_path(string)权重的存储位置
        output: weights(mat)将权重存到矩阵中
                m(int)权重的行数
                n(int)权重的列数
        '''
        f = open(weights_path)
        w = []
        for line in f.readlines():
            w_tmp = []
            lines = line.strip().split("	")
            for x in lines:
                w_tmp.append(float(x))
            w.append(w_tmp)
        f.close()
        weights = np.mat(w)
        m, n = np.shape(weights)
        return weights, m, n
    该程序中,需要导入 random 模块,这个模块的主要功能是为了生成下面的测试数据。在 load_weights 函数中,其输入为模型权重所在文件 weights_path,其输出为权重所在的矩阵,以及权重矩阵的行数 m 和列数 n。

    load_data 函数的具体实现代码如下所示:
    def load_data(num, m):
        '''导入测试数据
        input:  num(int)生成的测试样本的个数
                m(int)样本的维数
        output: testDataSet(mat)生成测试样本
        '''
        testDataSet = np.mat(np.ones((num, m)))
        for i in xrange(num):
            testDataSet[i, 1] = rd.random() * 6 - 3#随机生成[-3,3]之间的随机数
            testDataSet[i, 2] = rd.random() * 15#随机生成[0,15]之间是的随机数
        return testDataSet
    该程序中,load_data 函数用于生成测试样本,其中,函数的输入为样本的个数 num 和样本的维数 m。其输出为生成的测试样本 testDataSet。在生成样本的过程中使用到了 random 模块中的 random()方法,该方法主要是生成(0.0,1.0)之间的随机数。因此,需要在“softmax_regression_test.py”文件中导入 random 模块:
    import random as rd
    predict 函数的具体实现如下所示:
    def predict(test_data, weights):
        '''利用训练好的Softmax模型对测试数据进行预测
        input:  test_data(mat)测试数据的特征
                weights(mat)模型的权重
        output: h.argmax(axis=1)所属的类别
        '''
        h = test_data * weights
        return h.argmax(axis=1)#获得所属的类别
    在程序中,predict 函数对测试数据进行了预测,并将最终的预测结果存到 h 中,predict 函数的输入为测试数据 test_data 和模型的权重 weights,函数的输出是每个测试样本对应的类别。在函数中,得到了每个样本属于每一个类别的概率,最终返回概率值最大的 index 作为最终的类别标签。

    在本次测试中随机生成了 4 000 个样本,目的是为了能够更好地刻画出分类的边界,最终的分类效果如图 2 所示。


    图 2 最终的分类边界

    在图 2 中,通过点的不同深浅区分出 4 个类别之间的边界。最终利用 save_result 函数将预测的结果保存到指定的文件中,save_result 函数的具体实现为:
    def save_result(file_name, result):
        '''保存最终的预测结果
        input:  file_name(string):保存最终结果的文件名
                result(mat):最终的预测结果
        '''
        f_result = open(file_name, "w")
        m = np.shape(result)[0]
        for i in xrange(m):
            f_result.write(str(result[i, 0]) + "
    ")
        f_result.close()
    此程序中,函数 save_result 将最终的预测结果 result 保存到指定的文件 file_name 中。save_result 函数的输入分别为最终的预测结果 result 和保存的文件名 file_name。