MNIST逻辑回归实现

先放代码


import os
import struct
import numpy as np
import matplotlib.pyplot as plt
import gzip
import tempfile
import random
import tensorflow as tf

#*****************************************************************************************
#从文件中读入数据

def load_mnist(labels_path,images_path):
    """Load MNIST data from `path`"""
    with open(labels_path, 'rb') as lbpath:
        magic, n = struct.unpack('>II',
                                 lbpath.read(8))
        labels = np.fromfile(lbpath,
                             dtype=np.uint8)

    with open(images_path, 'rb') as imgpath:
        magic, num, rows, cols = struct.unpack('>IIII',
                                               imgpath.read(16))
        images = np.fromfile(imgpath,
                             dtype=np.uint8).reshape(len(labels), 784)

    return images, labels

train_labels_path = 'C:/Users/cxt66/Desktop/MNISTdata/MNISTdata/train-labels.idx1-ubyte'
train_images_path = 'C:/Users/cxt66/Desktop/MNISTdata/MNISTdata/train-images.idx3-ubyte'
test_labels_path = 'C:/Users/cxt66/Desktop/MNISTdata/MNISTdata/t10k-labels.idx1-ubyte'
test_images_path = 'C:/Users/cxt66/Desktop/MNISTdata/MNISTdata/t10k-images.idx3-ubyte'
(train_images,train_labels)= load_mnist(train_labels_path,train_images_path)
(test_images,test_labels)= load_mnist(test_labels_path,test_images_path)
#************************************************************************************************
#对数据进行转化,使其符合格式

def transfer(labels,number):#对labels进行转化,从单个数字变成one-hot向量
    final_labels=[]
    for i in range(number):
        if(labels[i] == 0):
            label = [1.0,0,0,0,0,0,0,0,0,0]
        elif(labels[i] == 1):
            label = [0,1,0,0,0,0,0,0,0,0]
        elif(labels[i] == 2):
            label = [0,0,1,0,0,0,0,0,0,0]
        elif(labels[i] == 3):
            label = [0,0,0,1,0,0,0,0,0,0]
        elif(labels[i] == 4):
            label = [0,0,0,0,1,0,0,0,0,0]
        elif(labels[i] == 5):
            label = [0,0,0,0,0,1,0,0,0,0]
        elif(labels[i] == 6):
            label = [0,0,0,0,0,0,1,0,0,0]
        elif(labels[i] == 7):
            label = [0,0,0,0,0,0,0,1,0,0]
        elif(labels[i] == 8):
            label = [0,0,0,0,0,0,0,0,1,0]
        else:
            label = [0,0,0,0,0,0,0,0,0,1]
        final_labels.append(label)
    return final_labels

train_new_images = train_images.astype(dtype = np.float)/255
test_new_images = test_images.astype(dtype = np.float)/255

test_new_labels = np.array(transfer(test_labels,10000)).astype(dtype = np.float)
train_new_labels = np.array(transfer(train_labels,60000)).astype(dtype = np.float)

#********************************************************************************
#训练核心代码
def next_batch(number):
    i = random.randrange(0,59899)
    batch_xs = train_new_images[i:i+number]
    batch_ys = train_new_labels[i:i+number]
    return batch_xs,batch_ys

x = tf.placeholder(tf.float32,[None,784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x,W)+b)
y_ = tf.placeholder("float",[None,10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

for i in range(10000):
    batch_xs,batch_ys = next_batch(100)
    print('loss',sess.run(cross_entropy,feed_dict = {x: batch_xs,y_: batch_ys}))                                                      
    sess.run(train_step,feed_dict = {x: batch_xs,y_: batch_ys})

#********************************
#结果检验
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
print(sess.run(accuracy, feed_dict={x:test_new_images, y_: test_new_labels}))


 

 

 这个是在极客学院的入门代码上改的。

因为没法直接下载到解数据的函数,只能自己写。

可以从网上找到压缩包,解压之后是这样的

四个ubyte文件

然后用第一段的函数读进来,再用第二段的函数转成标准数据流。

第三段是核心的训练过程,第四段是用测试集来进行检验。

原文地址:

http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html

作为刚转专业过来,还没入门的小菜鸟,表示写一写很头痛,又很开心,遇到好多问题,慢慢的都解决掉了,希望以后能再接再厉。 

<think>好的,我需要帮助用户找到用C语言实现基于MNIST数据集的逻辑回归的代码示例或教程。首先,我得回忆一下MNIST数据集的结构,它包含28x28像素的手写数字图像,通常存储为像素值加上标签。逻辑回归虽然名字里有“回归”,但实际上是用于分类的,特别是二分类,但MNIST是10个类别,所以可能需要用softmax回归,也就是多类逻辑回归。 用户提到他们想要C语言的例子,但根据提供的引用,原教程是使用Python和Theano的[^4]。所以可能需要寻找其他资源。我需要考虑用户可能没有现成的C代码,可能需要自己实现。这时候应该给出实现步骤,指导用户如何从零开始构建。 首先,数据加载部分。MNIST数据集通常以二进制格式存储,C语言需要读取这些文件。可能需要解析训练图像和标签文件的结构。比如,训练图像文件的前16字节是魔数、图像数量、行数、列数等信息,接着是像素数据。标签文件类似,前8字节是魔数和数量,之后是每个标签。用户需要编写函数来读取这些数据到内存中。 然后,逻辑回归模型的实现。模型参数包括权重矩阵和偏置向量。因为MNIST有10个类别,所以权重矩阵的维度应该是784x10(每个像素对应10个类别的权重),偏置是10维向量。前向计算是输入向量与权重矩阵相乘,加上偏置,再经过softmax函数得到概率分布。损失函数通常使用交叉熵损失,加上L2正则化防止过拟合。 接下来是梯度下降优化。需要计算损失函数对权重和偏置的梯度,然后更新参数。手动推导梯度可能会有点复杂,特别是对于softmax和交叉熵的组合。不过根据引用[^3],逻辑回归通过概率来进行分类,所以需要确保概率计算正确。 用户可能需要参考数值计算库,比如自己实现矩阵运算,或者使用现有的库如BLAS,但C语言标准库没有这些,可能需要简化实现。例如,使用嵌套循环进行矩阵乘法,手动计算softmax和梯度。 代码示例部分,可以提供一个简单的框架,包括数据加载、参数初始化、前向传播、损失计算、反向传播和参数更新。但由于时间和篇幅限制,可能无法提供完整的代码,但可以给出关键步骤的伪代码或结构,比如如何定义权重矩阵,如何计算softmax,以及梯度下降的步骤。 此外,用户可能需要预处理数据,比如将像素值归一化到0-1之间,标签进行one-hot编码。但one-hot编码在C中可能需要手动处理,用数组表示。 测试部分,需要计算准确率,比较预测结果和真实标签。在迭代训练过程中,每隔一定次数输出损失和准确率,以监控训练效果。 关于优化,可以提到学习率调整、批量大小选择、正则化参数等。引用[^2]提到了使用Theano实现逻辑回归教程,虽然是用Python,但其中的数学原理是相同的,用户可以借鉴到C的实现中。 可能遇到的问题包括内存管理,C语言需要手动分配和释放数组内存,特别是处理大量数据时需要注意效率。此外,数值稳定性,比如在计算softmax时指数可能导致溢出,需要减去最大值等技巧。 最后,建议用户参考现有的开源项目或大学课程作业,可能会有C实现的例子。如果没有现成的,可能需要结合多个资源,如MNIST的数据解析教程和逻辑回归的理论实现,自行整合成C代码。</think>### 用C语言实现MNIST数据集的逻辑回归 #### 1. **实现步骤** **a. 数据加载与预处理** MNIST数据集包含60,000个训练样本和10,000个测试样本,每个样本为28x28的灰度图像(784维向量)和一个标签(0-9)。 - **数据格式解析**: - 图像文件(如`train-images-idx3-ubyte`)前16字节为文件头,包含魔数、图像数量、行数、列数。 - 标签文件(如`train-labels-idx1-ubyte`)前8字节为魔数和标签数量。 - **C语言实现**:使用`fread`读取二进制文件,并将像素值归一化为$[0,1]$。 **b. 模型定义** 逻辑回归(多分类需用softmax回归)的数学形式: $$ P(y=k \mid x) = \frac{e^{W_k x + b_k}}{\sum_{j=1}^{10} e^{W_j x + b_j}} $$ 其中,$W$为权重矩阵(维度784x10),$b$为偏置向量(维度10)。 **c. 损失函数与优化** - **交叉熵损失**: $$ L = -\frac{1}{N} \sum_{i=1}^N \sum_{k=1}^{10} y_{i,k} \log(P_{i,k}) + \lambda \|W\|^2 $$ 其中$\lambda$为L2正则化系数。 - **梯度下降**:通过反向传播计算梯度$\frac{\partial L}{\partial W}$和$\frac{\partial L}{\partial b}$,并更新参数。 #### 2. **代码框架示例** ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define INPUT_DIM 784 #define OUTPUT_DIM 10 #define LEARNING_RATE 0.01 #define EPOCHS 100 // 加载MNIST数据(需自行实现) void load_mnist(const char *image_path, const char *label_path, float **images, int *labels); // Softmax函数 void softmax(float *logits, float *probabilities, int n) { float max_val = logits[0]; for (int i = 1; i < n; i++) { if (logits[i] > max_val) max_val = logits[i]; } float sum = 0.0; for (int i = 0; i < n; i++) { probabilities[i] = exp(logits[i] - max_val); sum += probabilities[i]; } for (int i = 0; i < n; i++) probabilities[i] /= sum; } // 训练逻辑回归 void train(float **train_images, int *train_labels, int num_samples) { // 初始化权重和偏置 float W[INPUT_DIM][OUTPUT_DIM] = {0}; float b[OUTPUT_DIM] = {0}; for (int epoch = 0; epoch < EPOCHS; epoch++) { float total_loss = 0.0; for (int i = 0; i < num_samples; i++) { // 前向传播 float logits[OUTPUT_DIM] = {0}; for (int k = 0; k < OUTPUT_DIM; k++) { for (int j = 0; j < INPUT_DIM; j++) { logits[k] += train_images[i][j] * W[j][k]; } logits[k] += b[k]; } // 计算softmax概率 float probs[OUTPUT_DIM]; softmax(logits, probs, OUTPUT_DIM); // 计算损失和梯度 float dW[INPUT_DIM][OUTPUT_DIM] = {0}; float db[OUTPUT_DIM] = {0}; int true_label = train_labels[i]; for (int k = 0; k < OUTPUT_DIM; k++) { float gradient = probs[k] - (k == true_label ? 1.0 : 0.0); for (int j = 0; j < INPUT_DIM; j++) { dW[j][k] += train_images[i][j] * gradient; } db[k] += gradient; } // 更新权重和偏置 for (int j = 0; j < INPUT_DIM; j++) { for (int k = 0; k < OUTPUT_DIM; k++) { W[j][k] -= LEARNING_RATE * (dW[j][k]/num_samples + 0.01*W[j][k]); // L2正则化 } } for (int k = 0; k < OUTPUT_DIM; k++) { b[k] -= LEARNING_RATE * db[k]/num_samples; } } printf("Epoch %d, Loss: %.4f\n", epoch, total_loss/num_samples); } } int main() { float *train_images; int *train_labels; load_mnIST("train-images-idx3-ubyte", "train-labels-idx1-ubyte", &train_images, &train_labels); train(train_images, train_labels, 60000); return 0; } ``` #### 3. **关键说明** - **数据加载**:需要自行实现MNIST文件的二进制解析(参考官方格式说明)。 - **性能优化**:上述代码为简化版本,实际中需使用批量计算和矩阵运算优化速度。 - **扩展性**:可加入学习率衰减、随机梯度下降(SGD)等优化方法[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值