逻辑回归实现数字手写识别

逻辑回归实现数字手写识别

我是用自己写的算法实现数字手写识别,采用的是Mnist的数据集,因为数据过多,所以我训练集取了600张,测试集取了100张

提取图片

因为mnist的数据集下载的是ubyte格式,我先把他转成jpg格式。

代码如下:

def readfile():  # 读取源图片文件
    with open('E:\\pycharm\\python-代码\\train-images.idx3-ubyte', 'rb') as f1:
        buf1 = f1.read()
    return buf1
   
def get_image(buf1):  # 解析并保存图片
    image_index = 0
    image_index += struct.calcsize('>IIII')
    magic, numImages, imgRows, imgCols = struct.unpack_from(">IIII", buf1, 0)
    im = []
    for i in range(numImages):
        temp = struct.unpack_from('>784B', buf1, image_index)
        im = np.array(temp)
        im2 = im.reshape(28, 28)
        cv2.imwrite("E:\\train\\testIM" + str(i) + ".jpg", im2)  # 保存路径自己设置
        image_index += struct.calcsize('>784B')  # 28*28=784(B)
        if i % 20 == 0:  # 知道图片保存的进度
            print(i)
        else:
            print(i, )

把图片转化成像素以及提取图片的标签

mnist数据集的图片都是28 x 28的,像素提取出来以后的矩阵也是28 x 28的。我把像素的矩阵转化为1 x 784的向量。600张图片即为600 x 784的矩阵,再进行转置,变为784 x 600的矩阵。

def gettrainImages():  # 得到训练集像素
    train_set = np.zeros([train_num, 784], int)  # 建立一个600行,784列的空矩阵
    for i in range(0, train_num):
        print("训练集第"+str(i)+"张图片")
        img = np.array(Image.open('E:/train/testIM' + str(i) + '.jpg'))  # 读取前600张图片的像素
        for rows in range(28):
            for cols in range(28):
                if img[rows, cols] >= 127:  # 若灰度值大于等于127,则为1,否则为0
                    img[rows, cols] = 1
                else:
                    img[rows, cols] = 0
                train_set[i, rows * 28 + cols] = img[rows, cols]
    train_flatten = np.transpose(train_set)  # 转置像素
    return train_flatten
    
def gettrainLabels():  # 解析训练标签(解析出来的标签和图片顺序是一一对应的)
    f1 = open("C:\\Users\\84782\\Desktop\\Mnist\\train-labels.idx1-ubyte", 'rb')
    buf1 = f1.read()
    f1.close()
    index = 0
    magic, num = struct.unpack_from(">II", buf1, 0)
    index += struct.calcsize('>II')
    labs = []
    labs = struct.unpack_from('>' + str(num) + 'B', buf1, index)
    labs_change = np.zeros((10, train_num))
    for i in range(0, 10):  # 改变训练集标签,第一行非零数标签为0,0的标签为1;第二行不是1的数标签为0,1的标签为1,以此类推
        for j in range(0, train_num):
            if labs[j] == i:
                labs_change[i, j] = 1
            else:
                labs_change[i, j] = 0
    return labs_change, labs  # 返回训练集标签
训练集最后的维度为:(784, 600)
训练集标签的维度为:(10, 600)
测试集最后的维度为:(784, 100)
测试集标签的维度为:(1, 100)

提取测试集像素也是一样的。

sigmoid函数

def sigmoid(z):
    s = 1 / (1 + np.exp(-z))
    return s

计算代价函数和求出w和b的偏导数

def propagate(w, b, X, Y):
    A = sigmoid(np.dot(w.T, X) + b)
    cost = (-1 / train_num) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A)))  # 计算代价

    dw = (1 / train_num) * np.dot(X, (A - Y).T)
    db = (1 / train_num) * np.sum(A - Y)

    # 创造一个字典,保存dw和db
    grads = {
        "dw": dw,
        "db": db
    }
    return grads, cost

梯度下降,优化参数w和b

def optimize(w, b, X, Y, num_iterations, learning_rate):
    costs = []
    for i in range(num_iterations):
        grads, cost = propagate(w, b, X, Y)
        dw = grads["dw"]
        db = grads["db"]

        w = w - learning_rate * dw
        b = b - learning_rate * db

        if i % 100 == 0:
            costs.append(cost)
        if i % 100 == 0:
            print("迭代的次数:%i,误差值: %f" % (i, cost))

    return w, b

调用函数,生成十个分类器,然后开始训练和测试

# 0的分类器
print("\n开始训练0的分类器")
w0 = np.zeros((784, 1))
b0 = 0
w0, b0 = optimize(w0, b0, train_set, train_labc[0], num_iterations=500, learning_rate=1)
A0 = sigmoid(np.dot(w0.T, train_set) + b0)
fin_A[0] = A0
test_A0 = sigmoid(np.dot(w0.T, test_set) + b0)
test_A[0] = test_A0

# 1的分类器
print("\n开始训练1的分类器")
w1 = np.zeros((784, 1))
b1 = 0
w1, b1 = optimize(w1, b1, train_set, train_labc[1], num_iterations=500, learning_rate=1)
A1 = sigmoid(np.dot(w1.T, train_set) + b1)
fin_A[1] = A1
test_A1 = sigmoid(np.dot(w1.T, test_set) + b1)
test_A[1] = test_A1

# 2的分类器
print("\n开始训练2的分类器")
w2 = np.zeros((784, 1))
b2 = 0
w2, b2 = optimize(w2, b2, train_set, train_labc[2], num_iterations=500, learning_rate=1)
A2 = sigmoid(np.dot(w2.T, train_set) + b2)
fin_A[2] = A2
test_A2 = sigmoid(np.dot(w2.T, test_set) + b2)
test_A[2] = test_A2

# 3的分类器
print("\n开始训练3的分类器")
w3 = np.zeros((784, 1))
b3 = 0
w3, b3 = optimize(w3, b3, train_set, train_labc[3], num_iterations=500, learning_rate=1)
A3 = sigmoid(np.dot(w3.T, train_set) + b3)
fin_A[3] = A3
test_A3 = sigmoid(np.dot(w3.T, test_set) + b3)
test_A[3] = test_A3

# 4的分类器
print("\n开始训练4的分类器")
w4 = np.zeros((784, 1))
b4 = 0
w4, b4 = optimize(w4, b4, train_set, train_labc[4], num_iterations=500, learning_rate=1)
A4 = sigmoid(np.dot(w4.T, train_set) + b4)
fin_A[4] = A4
test_A4 = sigmoid(np.dot(w4.T, test_set) + b4)
test_A[4] = test_A4

# 5的分类器
print("\n开始训练5的分类器")
w5 = np.zeros((784, 1))
b5 = 0
w5, b5 = optimize(w5, b5, train_set, train_labc[5], num_iterations=500, learning_rate=1)
A5 = sigmoid(np.dot(w5.T, train_set) + b5)
fin_A[5] = A5
test_A5 = sigmoid(np.dot(w5.T, test_set) + b5)
test_A[5] = test_A5

# 6的分类器
print("\n开始训练6的分类器")
w6 = np.zeros((784, 1))
b6 = 0
w6, b6 = optimize(w6, b6, train_set, train_labc[6], num_iterations=500, learning_rate=1)
A6 = sigmoid(np.dot(w6.T, train_set) + b6)
fin_A[6] = A6
test_A6 = sigmoid(np.dot(w6.T, test_set) + b6)
test_A[6] = test_A6

# 7的分类器
print("\n开始训练7的分类器")
w7 = np.zeros((784, 1))
b7 = 0
w7, b7 = optimize(w7, b7, train_set, train_labc[7], num_iterations=500, learning_rate=1)
A7 = sigmoid(np.dot(w7.T, train_set) + b7)
fin_A[7] = A7
test_A7 = sigmoid(np.dot(w7.T, test_set) + b7)
test_A[7] = test_A7

# 8的分类器
print("\n开始训练8的分类器")
w8 = np.zeros((784, 1))
b8 = 0
w8, b8 = optimize(w8, b8, train_set, train_labc[8], num_iterations=500, learning_rate=1)
A8 = sigmoid(np.dot(w8.T, train_set) + b8)
fin_A[8] = A8
test_A8 = sigmoid(np.dot(w8.T, test_set) + b8)
test_A[8] = test_A8

# 9的分类器
print("\n开始训练9的分类器")
w9 = np.zeros((784, 1))
b9 = 0
w9, b9 = optimize(w9, b9, train_set, train_labc[4], num_iterations=2000, learning_rate=5)
A9 = sigmoid(np.dot(w9.T, train_set) + b9)
fin_A[9] = A9
test_A9 = sigmoid(np.dot(w9.T, test_set) + b9)
test_A[9] = test_A9

训练结果保存到一个10行600列的数组
测试结果保存到一个10行100列的数组

最后开始测试准确率

for i in range(train_num):  # 训练集的准确率
    trainnum_max = 0  # 更新num_max
    train_max = 0
    for j in range(10):
        if fin_AT[i, j] >= train_max:
            trainnum_max = j
            train_max = fin_AT[i, j]
    answer_train[0, i] = trainnum_max
    if answer_train[0, i] == train_lab[i]:
        right += 1

for i in range(test_num):  # 测试集的准确率
    testnum_max = 0
    test_max = 0
    for j in range(10):
        if test_AT[i, j] >= test_max:
            testnum_max = j
            test_max = test_AT[i,j]
    answer_test[0, i] =testnum_max
    if answer_test[0, i] == test_lab[0, i]:
        right_test += 1

最后的结果

600张训练集,100张测试集的结果

训练集准确率为:87.33333333333333%
测试集准确率为:79.0%
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值