当前位置:   article > 正文

py实现多分类正则化逻辑回归手写训练集(精炼加注)_基于手写逻辑回归的分类训练

基于手写逻辑回归的分类训练

py实现多分类逻辑回归手写训练集(精炼)

这几天再补吴恩达的作业,刚好以前的逻辑回归代码还没实现,这边就先贴上来。
作业中只给到5000个训练样本,且0的标签为10。代码中拿了4000个作为训练,1000个测试

import scipy.optimize as opt
import scipy.io as scio
import matplotlib.pyplot as plt
import numpy as np
'''***************************************************************
 * @Fun_Name    : def loadData(filename)
 * @Function    : 从数据中分离特征和标签,加入每个样本的第一个特征1,并且将其打乱,前4000个样本做训练集,后1000个训练集
 * @Parameter   : 文件名
 * @Return      : 特征 (5000400) 标签 (50001) array
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 10:10 2020-06-08***'''
def loadData(filename , rand):
    mat = scio.loadmat(filename)                                          #得到数据类型为字典
    labels = mat['y']                                                     #将header是y的放在数组中
    features = mat['X']                                                   #将header是X的放在数组中
    m = features.shape[0]                                                 #得到样本数
    column = np.ones(m)                                                   #得到(m,)都为1的列表
    features = np.insert(features,0,values=column,axis=1)                 #插入到样本第一列
    # 将数据打乱 4000个训练  1000个测试
    np.random.seed(rand)                                                  #rand随机种子,当rand一致时,features和labels打乱顺序一致,保证一一对应
    np.random.shuffle(features)                                           #打乱
    np.random.seed(rand)
    np.random.shuffle(labels)
    trainFeatures = features[0:4000,:]                                    #取前4000个作为训练样本
    testFeatures = features[4000:5000,:]                                  #后1000个位测试样本
    trainLabels = labels[0:4000]
    testLabels = labels[4000:5000]
    return trainFeatures ,testFeatures,trainLabels,testLabels
'''***************************************************************
 * @Fun_Name    : def visualizing(features , labels):
 * @Function    : 可视化,打乱后可用这个函数看看特征和标签是否对应
 * @Parameter   : 
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:01 2020-06-08***'''
def visualizing(features , labels):
    featuresShow = np.delete(features,0,axis=1)                           #要还原图象,要将特征中第一列添加的1舍去
    m = featuresShow.shape[0]                                             #得到样本个数
    image = featuresShow.reshape(m,20,20)                                 #将400->20,20维度
    for i in range(910,920):                                              #随便抽10张出来对比下看看是否对应
        plt.imshow(image[i].T)                                            #转置是为了原图是横着的,转置为了视觉效果更好
        print(labels[i])
        plt.show()
'''***************************************************************
 * @Fun_Name    : def sigmoid(z):
 * @Function    : 不做解释
 * @Parameter   : 
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:10 2020-06-08***'''
def sigmoid(z):
    return 1/(1 + np.exp(-z))
'''***************************************************************
 * @Fun_Name    : def dealLabels(labels,N):
 * @Function    : 为一对多训练做准备
 * @Parameter   : labels 标签 ,N训练的数字 ,比如训练2,那就将标签=2改为1,区域标签改为0
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:11 2020-06-08***'''
def dealLabels(labels,N):
    deallabels = labels.copy()                                             #深拷贝
    one = np.nonzero(deallabels == N)                                      #找到deallabels == N的索引
    zero = np.nonzero(deallabels != N)                                     #找到deallabels != N的索引
    deallabels[one] = 1                                                    #将deallabels == N的标签改为1
    deallabels[zero] = 0
    return deallabels
'''***************************************************************
 * @Fun_Name    : def cost(theta , features , labels , lamda): 
 * @Function    : 计算损失函数 正则化 下面都是公式
 * @Parameter   : 
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:14 2020-06-08***'''
def cost(theta , features , labels , lamda):
    m , n = features.shape
    theta = theta.reshape(n,1)
    A = sigmoid(np.dot(features, theta))
    cost1 = (- np.dot(labels,np.log(A)) - np.dot((1-labels),np.log(1-A)))/m
    cost2 = (lamda/(2*m))*np.dot(theta[1:n].T,theta[1:n])
    return (float)(cost1 + cost2)

'''***************************************************************
 * @Fun_Name    : def gradient(features , theta)
 * @Function    : 求梯度
 * @Parameter   : feature [5000,401] theta [401,1]
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 11:29 2020-06-08***'''
def gradient(theta , features , labels , lamda):
    m , n= features.shape
    theta = theta.reshape(n, 1)
    A = sigmoid(np.dot(features, theta)).reshape(m,1)
    gradient1 = np.dot(features.T,(A - labels.T))/m
    gradient2 = (lamda / m) * theta
    gradient2[0] = 0
    return (gradient2 + gradient1)
'''***************************************************************
 * @Fun_Name    : def onevsall(trainFeatures,trainLabels,lamda = 0.01):
 * @Function    : 一对多训练
 * @Parameter   : lamda正则化参数
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:19 2020-06-08***'''
def onevsall(trainFeatures,trainLabels,lamda = 0.01):
    m, n = trainFeatures.shape
    theta = np.zeros(shape=[10, n])                                         #将theta变成10,n 每一行记录一个数字训练好的参数
    #theta[0]记录的是数字1的训练参数,1是2,2是3,..9的话是0
    for i in range(1,11):                                                   #改数据集中0的标签值为10 所以从1开始到10
        deallabels = dealLabels(trainLabels, i).T  # 1,4000                 #看上面注解
        theta[i-1] = opt.fmin_tnc(func=cost, x0=theta[i-1], fprime=gradient, args=(trainFeatures, deallabels, lamda))[0].reshape(1,n)   #优化的梯度下降算法
        print("第%d/10次训练成功*****************************************************"%(i))
    return theta.T
'''***************************************************************
 * @Fun_Name    : def predict(theta,testFeatures,testLabels):
 * @Function    : 预测
 * @Parameter   : 
 * @Return      : 
 * @Creed       : Talk is cheap , show me the code
 ***********************xieqinyu creates in 21:22 2020-06-08***'''
def predict(theta,testFeatures,testLabels):
    m = testFeatures.shape[0]
    accury = 0
    Predict = np.dot(testFeatures,theta)                                    #每一行是每个样本在1 2 3 4 5 6 7 8 9 10 的概率值
    temp = Predict.argmax(axis=1) + 1                                       #求取每行的最大值的索引 加1是因为索引是0 1 2 3 4 5 6 7 8 9.0代表的是1 .......9代表十(实际上是0for i in range(m):
        if temp[i] == testLabels[i]:
            accury += 1
    print(float(accury/m))

trainFeatures ,testFeatures,trainLabels,testLabels  = loadData("ex3data1.mat",100)
predict(onevsall(trainFeatures,trainLabels,0.01),testFeatures,testLabels)




  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135

效果在正则化参数为0.01的情况下准确率在0.892,有时间可以画个lamda-cost图找最优的正则化参数

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/928253
推荐阅读
相关标签
  

闽ICP备14008679号