Dlib库dnn入门——手写字体识别

dlib下载地址:  地址


下载手写字体的训练集和测试集  地址

解压到同一个文件夹



然后需要配置一下dlib的环境

首先用cmake生成项目


编译生成后可以看到生成了dlib_release_64bit_msvc1910.lib


扫描二维码关注公众号,回复: 1022008 查看本文章

添加库目录,以及连接器输入




然后简单粗暴的代码(记得改下目录


// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*
This is an example illustrating the use of the deep learning tools from the
dlib C++ Library.  In it, we will train the venerable LeNet convolutional
neural network to recognize hand written digits.  The network will take as
input a small image and classify it as one of the 10 numeric digits between
0 and 9.

The specific network we will run is from the paper
LeCun, Yann, et al. "Gradient-based learning applied to document recognition."
Proceedings of the IEEE 86.11 (1998): 2278-2324.
except that we replace the sigmoid non-linearities with rectified linear units.

These tools will use CUDA and cuDNN to drastically accelerate network
training and testing.  CMake should automatically find them if they are
installed and configure things appropriately.  If not, the program will
still run but will be much slower to execute.
*/


#include <dlib/dnn.h>
#include <iostream>
#include <dlib/data_io.h>

using namespace std;
using namespace dlib;

int main(int argc, char** argv) try
{
	// 测试下MINIST数据集 
	

	// MNIST 中6W用来训练,1W用作测试,各自有标签信息,总共四个文件
	std::vector<matrix<unsigned char>> training_images;
	std::vector<unsigned long>         training_labels;
	std::vector<matrix<unsigned char>> testing_images;
	std::vector<unsigned long>         testing_labels;
	load_mnist_dataset("C:\\Users\\zhumingde\\Documents\\MINIST", training_images, training_labels, testing_images, testing_labels);


	// 现在开始定义LeNet
	//网络需要定义三个部分:输入、计算图、损失函数

	// The input layer here says the network expects to be given matrix<unsigned char>
	// objects as input.  In general, you can use any dlib image or matrix type here, or
	// even define your own types by creating custom input layers.
	//
	// Then the middle layers define the computation the network will do to transform the
	// input into whatever we want.  Here we run the image through multiple convolutions,
	// ReLU units, max pooling operations, and then finally a fully connected layer that
	// converts the whole thing into just 10 numbers.  
	// 
	// Finally, the loss layer defines the relationship between the network outputs, our 10
	// numbers, and the labels in our dataset.  Since we selected loss_multiclass_log it
	// means we want to do multiclass classification with our network.   Moreover, the
	// number of network outputs (i.e. 10) is the number of possible labels.  Whichever
	// network output is largest is the predicted label.  So for example, if the first
	// network output is largest then the predicted digit is 0, if the last network output
	// is largest then the predicted digit is 9.  

	using net_type = loss_multiclass_log<
		fc<10,
		relu<fc<84,
		relu<fc<120,
		max_pool<2, 2, 2, 2, relu<con<16, 5, 5, 1, 1,
		max_pool<2, 2, 2, 2, relu<con<6, 5, 5, 1, 1,
		input<matrix<unsigned char>>
		>>>>>>>>>>>>;
	// This net_type defines the entire network architecture.  For example, the block
	// relu<fc<84,SUBNET>> means we take the output from the subnetwork, pass it through a
	// fully connected layer with 84 outputs, then apply ReLU.  Similarly, a block of
	// max_pool<2,2,2,2,relu<con<16,5,5,1,1,SUBNET>>> means we apply 16 convolutions with a
	// 5x5 filter size and 1x1 stride to the output of a subnetwork, then apply ReLU, then
	// perform max pooling with a 2x2 window and 2x2 stride.  



	// So with that out of the way, we can make a network instance.
	net_type net;
	// And then train it using the MNIST data.  The code below uses mini-batch stochastic
	// gradient descent with an initial learning rate of 0.01 to accomplish this.
	dnn_trainer<net_type> trainer(net);
	trainer.set_learning_rate(0.01);
	trainer.set_min_learning_rate(0.00001);
	trainer.set_mini_batch_size(128);
	trainer.be_verbose();
	// Since DNN training can take a long time, we can ask the trainer to save its state to
	// a file named "mnist_sync" every 20 seconds.  This way, if we kill this program and
	// start it again it will begin where it left off rather than restarting the training
	// from scratch.  This is because, when the program restarts, this call to
	// set_synchronization_file() will automatically reload the settings from mnist_sync if
	// the file exists.
	trainer.set_synchronization_file("mnist_sync", std::chrono::seconds(20));
	// Finally, this line begins training.  By default, it runs SGD with our specified
	// learning rate until the loss stops decreasing.  Then it reduces the learning rate by
	// a factor of 10 and continues running until the loss stops decreasing again.  It will
	// keep doing this until the learning rate has dropped below the min learning rate
	// defined above or the maximum number of epochs as been executed (defaulted to 10000). 
	trainer.train(training_images, training_labels);

	// At this point our net object should have learned how to classify MNIST images.  But
	// before we try it out let's save it to disk.  Note that, since the trainer has been
	// running images through the network, net will have a bunch of state in it related to
	// the last batch of images it processed (e.g. outputs from each layer).  Since we
	// don't care about saving that kind of stuff to disk we can tell the network to forget
	// about that kind of transient data so that our file will be smaller.  We do this by
	// "cleaning" the network before saving it.
	net.clean();
	serialize("mnist_network.dat") << net;
	// Now if we later wanted to recall the network from disk we can simply say:
	// deserialize("mnist_network.dat") >> net;


	// Now let's run the training images through the network.  This statement runs all the
	// images through it and asks the loss layer to convert the network's raw output into
	// labels.  In our case, these labels are the numbers between 0 and 9.
	std::vector<unsigned long> predicted_labels = net(training_images);
	int num_right = 0;
	int num_wrong = 0;
	// And then let's see if it classified them correctly.
	for (size_t i = 0; i < training_images.size(); ++i)
	{
		if (predicted_labels[i] == training_labels[i])
			++num_right;
		else
			++num_wrong;

	}
	cout << "training num_right: " << num_right << endl;
	cout << "training num_wrong: " << num_wrong << endl;
	cout << "training accuracy:  " << num_right / (double)(num_right + num_wrong) << endl;

	// Let's also see if the network can correctly classify the testing images.  Since
	// MNIST is an easy dataset, we should see at least 99% accuracy.
	predicted_labels = net(testing_images);
	num_right = 0;
	num_wrong = 0;
	for (size_t i = 0; i < testing_images.size(); ++i)
	{
		if (predicted_labels[i] == testing_labels[i])
			++num_right;
		else
			++num_wrong;

	}
	cout << "testing num_right: " << num_right << endl;
	cout << "testing num_wrong: " << num_wrong << endl;
	cout << "testing accuracy:  " << num_right / (double)(num_right + num_wrong) << endl;


	// Finally, you can also save network parameters to XML files if you want to do
	// something with the network in another tool.  For example, you could use dlib's
	// tools/convert_dlib_nets_to_caffe to convert the network to a caffe model.
	net_to_xml(net, "lenet.xml");
	system("pause");
}
catch (std::exception& e)
{
	cout << e.what() << endl;
	system("pause");
}


效果如图:



最后结果明天跑出来再放,2333,没用GPU太慢了233



猜你喜欢

转载自blog.csdn.net/zmdsjtu/article/details/79497954