使用LAP数据集进行年龄训练及估计

一、背景

原本是打算按《DEX Deep EXpectation of apparent age from a single image》进行表面年龄的训练,可由于IMDB-WIKI的数据集比较庞大,各个年龄段分布不均匀,难以划分训练集及验证集。后来为了先跑通整个训练过程的主要部分,就直接用LAP数据集,参考caffe的finetune_flickr_style,进行一些参数修改,利用bvlc_reference_caffenet.caffemodel完成年龄估计的finetune。

二、训练数据集准备

1、下载LAP数据集,包括Train、Validation、Test,以及对应的年龄label,http://chalearnlap.cvc.uab.es/dataset/18/description/,需要注册。

2、将标注好的csv文件转换为caffe识别的txt格式。csv每一行的信息为:图片名、年龄、标准差。训练的时候不需要标准差信息,我们只要将图片名和年龄写入到txt中,并按空格隔开,得到Train.txt如下:

同样,完成验证集cvs文件的转换,得到Validation.txt。

三、模型及相关文件拷贝

1、拷贝预训练好的vgg16模型caffe\models\bvlc_reference_caffenet\bvlc_reference_caffenet.caffemodel至工作目录下,该文件约232M;

2、拷贝caffe\models\finetune_flickr_style文件夹中deploy.prototxt、solver.prototxt、train_val.prototxt至工作目录下;

3、拷贝imageNet的均值文件caffe\data\ilsvrc12\imagenet_mean.binaryproto至工作目录下。

四、参数修改

1、修改train_val.prototxt

以及最后的输出层个数,因为我们要训练的为[0,100]岁的输出,共101类,所以:

2、修改solver.protxt

3、修改用于实际测试的部署文件deploy.protxt

输出层的个数也要改:

五、开始训练

1、新建train.bat

caffe train -solver solver.prototxt -weights bvlc_reference_caffenet.caffemodel
rem caffe train --solver solver.prototxt --snapshot snapshot/bvlc_iter_48000.solverstate
pause

双击即可开始训练,当训练过程中出现意外中断,可注释第一行,关闭第二行注释,根据实际情况修改保存,继续双击训练。

我的电脑CPU是i5 6500,显卡为gtx1050Ti,8G内存,大致要训练10个小时吧,中途也出现了一些内存不足训练终止的情况。

2、训练结束

六、模型评价

年龄估计原本是一个线性问题,不是一个明确的分类问题,人都无法准确无误地得到某人的年龄,更何况是机器呢。所以评价这个年龄分类模型的好坏不能简单地通过精度来衡量,可以用MAE(平均绝对误差)以及ε-error来衡量,其中

1、对验证集Validation.txt的所有图片进行预测

借助 https://github.com/eveningglow/age-and-gender-classification ,其环境搭建可参考https://www.cnblogs.com/smbx-ztbz/p/9399016.html

修改main函数

int split(std::string str, std::string pattern, std::vector<std::string> &words)
{
    std::string::size_type pos;
    std::string word;
    int num = 0;
    str += pattern;
    std::string::size_type size = str.size();
    for (auto i = 0; i < size; i++) {
        pos = str.find(pattern, i);
        if (pos == i) {
            continue;//if first string is pattern
        }
        if (pos < size) {
            word = str.substr(i, pos - i);
            words.push_back(word);
            i = pos + pattern.size() - 1;
            num++;
        }
    }
    return num;
}

//param example: model/deploy_age2.prototxt model/age_net.caffemodel model/mean.binaryproto img/0008.jpg
int main(int argc, char* argv[])
{
    if (argc != 5)
    {
        cout << "Command shoud be like ..." << endl;
        cout << "AgeAndGenderClassification ";
        cout << " \"AGE_NET_MODEL_FILE_PATH\" \"AGE_NET_WEIGHT_FILE_PATH\" \"MEAN_FILE_PATH\" \"TEST_IMAGE\" " << endl;
        std::cout << "argc = " << argc << std::endl;
        getchar();
        return 0;
    }

    // Get each file path
    string age_model(argv[1]);
    string age_weight(argv[2]);
    string mean_file(argv[3]);
    //string test_image(argv[4]);

    // Probability vector
    vector<Dtype> prob_age_vec;

    // Set mode
    Caffe::set_mode(Caffe::GPU);

    // Make AgeNet
    AgeNet age_net(age_model, age_weight, mean_file);

    // Initiailize both nets
    age_net.initNetwork();

    //读取待测试的图片名
    std::ifstream fin("E:\\caffe\\DEX_age_gender_predict\\lap2\\Validation.txt");
    std::string line;
    std::vector<std::string> test_images;
    std::vector<int> test_images_age;
    while (!fin.eof()) {
        std::getline(fin, line);
        std::vector<std::string> words;
        split(line, " ", words);
        test_images.push_back(words[0]);
        test_images_age.push_back(atoi(words[1].c_str()));
    }
    std::cout << "test_images size = " << test_images.size() << std::endl;

    std::ofstream fout("E:\\caffe\\DEX_age_gender_predict\\lap2\\Validation_predict.txt");
    for (int k = 0; k < test_images.size(); ++k) {
        std::cout << "k = " << k << std::endl;
        std::string test_image;
        test_image = test_images[k];

        // Classify and get probabilities
        Mat test_img = imread(test_image, CV_LOAD_IMAGE_COLOR);
        int age = age_net.classify(test_img, prob_age_vec);

        // Print result and show image
        //std::cout << "prob_age_vec size = " << prob_age_vec.size() << std::endl;
        //for (int i = 0; i < prob_age_vec.size(); ++i) {
        //    std::cout << "[" << i << "] = " << prob_age_vec[i] << std::endl;
        //}

        //Dtype prob;
        //int index;
        //get_max_value(prob_age_vec, prob, index);
        //std::cout << "prob = " << prob << ", index = " << index << std::endl;

        //imshow("AgeAndGender", test_img);
        //waitKey(0);
        fout << test_images[k] << " " << test_images_age[k] << " " << age << std::endl;

    }

    std::cout << "finish!" << std::endl;
    getchar();
    return 0;
}

我的命令参数为:E:\caffe\DEX_age_gender_predict\lap2\deploy.prototxt E:\caffe\DEX_age_gender_predict\lap2\snapshot\bvlc_iter_50000.caffemodel model\mean.binaryproto img\0008.jpg

可根据实际情况修改。可得到Validation_predict.txt文件。运行过程中可能会因为内存不足中断运行,可能要分批次运行多次。

2、计算MAE及ε-error

(1)将Validation_predict.txt文件及验证集的标注文件Reference.csv拷贝到新建的vs项目的工作目录下;

(2)计算

#include <iostream>
#include <string>
#include <fstream>
#include <vector>

int split(std::string str, std::string pattern, std::vector<std::string> &words)
{
    std::string::size_type pos;
    std::string word;
    int num = 0;
    str += pattern;
    std::string::size_type size = str.size();
    for (auto i = 0; i < size; i++) {
        pos = str.find(pattern, i);
        if (pos == i) {
            continue;//if first string is pattern
        }
        if (pos < size) {
            word = str.substr(i, pos - i);
            words.push_back(word);
            i = pos + pattern.size() - 1;
            num++;
        }
    }
    return num;
}

int main(int argc, char** argv)
{
    //u, sigma, x
    std::vector<int> u;
    std::vector<float> sigma;
    std::vector<int> predict;

    std::string line;
    std::ifstream csv_file("Reference.csv");
    while (!csv_file.eof()) {
        std::getline(csv_file, line);
        std::vector<std::string> words;
        split(line, ";", words);
        u.push_back(atoi(words[1].c_str()));
        sigma.push_back(atof(words[2].c_str()));
    }
    std::ifstream predict_file("Validation_predict.txt");
    while (!predict_file.eof()) {
        std::getline(predict_file, line);
        std::vector<std::string> words;
        split(line, " ", words);
        predict.push_back(atoi(words[2].c_str()));
    }
    if (u.size() != predict.size()) {
        std::cout << "u.size() != predict.size()" << std::endl;
        getchar();
        return -1;
    }

    //MAE
    int sum_err = 0;
    float MAE = 0;
    for (int i = 0; i < u.size(); ++i) {
        sum_err += abs(u[i] - predict[i]);
    }
    MAE = static_cast<float>(sum_err) / u.size();
    std::cout << "MAE = " << MAE << std::endl;//11.7184

    //esro-error
    std::vector<float> errors;
    float err = 0;
    float error = 0.0;
    for (int i = 0; i < u.size(); ++i) {
        err = 1.0 - exp(-1.0*(predict[i] - u[i])*(predict[i] - u[i]) / (2 * sigma[i] * sigma[i]));
        errors.push_back(err);
        error += err;
    }
    error /= errors.size();
    std::cout << "error = " << error << std::endl;//0.682652

    std::cout << "finish!" << std::endl;
    getchar();
    return 0;
}

最终得到MAE为11.7184, ε-error为0.682652。

七、实际应用中预测

1、可利用caffe提供的classification工具对输入图片地进行估计

classification deploy.prototxt snapshot\bvlc_iter_50000.caffemodel imagenet_mean.binaryproto ..\age_labels.txt ..\test_image\test_3.jpg
pause

其中,age_labels.txt为0-100个label的说明信息,每个label对应一行,共101行,我的写法如下:

end

原文地址:https://www.cnblogs.com/smbx-ztbz/p/9744970.html

时间: 2024-11-05 18:35:57

使用LAP数据集进行年龄训练及估计的相关文章

如何把数据集划分成训练集和测试集

本文内容来自周志阳<机器学习> 问题: 对于一个只包含\(m\)个样例的数据集\(D=\{(x_1,y_1),(x_2,y_2),\cdots,(x_m,y_m)\),如何适当处理,从\(D\)中产生训练集\(S\)和测试集\(T\)? 下面介绍三种常见的做法: 留出法 交叉验证法 自助法 留出法(hold-out) 留出法直接将数据集\(D\)划分为两个互斥的集合,其中一个集合作为训练集\(S\),留下的集合作为测试集\(T\),即\(D=S \cup T, S \cap T=\emptys

openface 训练数据集

训练深度网络模型OpenFace还不是运用faceNet的model作为训练模型,所以在准确性上比faceNet要低,如果你只是做一个简单的分类,建议你看看官网的demo3(http://cmusatyalab.github.io/openface/demo-3-classifier/),如果你想自己训练一个模型,建议提供一个大于500k的图片集作为训练集.(这里的500k应该是50w张图片来理解更合适)Openface暂时还没提供该faceNet模型的支持.注意:在K40Gpu的机器上训练数据

sklearn训练感知器用iris数据集

简化版代码 1 from sklearn import datasets 2 import numpy as np 3 4 #获取data和类标 5 iris = datasets.load_iris() 6 X = iris.data[:,[2,3]] 7 y = iris.target 8 9 #测试样本和训练样本三七分 10 from sklearn.model_selection import train_test_split 11 X_train,X_test,y_train,y_te

DeepLabv3+图像语义分割实战:训练自己的数据集

DeepLabv3+是一种非常先进的基于深度学习的图像语义分割方法,可对物体进行像素级分割. 本课程将手把手地教大家使用labelme图像标注工具制造自己的数据集,并使用DeepLabv3+训练自己的数据集,从而能开展自己的图像分割应用. 课程链接:https://edu.51cto.com/course/18817.html 本课程有两个项目实践: (1) CamVid语义分割 :对CamVid数据集进行语义分割 (2) RoadScene语义分割:对汽车行驶场景中的路坑.车.车道线等进行物体

U-Net图像语义分割实战:训练自己的数据集

U-Net是一种基于深度学习的图像语义分割方法,尤其在医学图像分割中表现优异. 本课程将手把手地教大家使用labelme图像标注工具制作自己的数据集,生成Mask图像,并使用U-Net训练自己的数据集,从而能开展自己的图像分割应用. 课程链接:https://edu.51cto.com/course/18936.html 本课程有三个项目实践: (1) Kaggle盐体识别比赛 :利用U-Net进行Kaggle盐体识别 (2) Pothole语义分割:对汽车行驶场景中的路坑进行标注和语义分割 (

开源数据集

Images Analysis 数据集 介绍 备注 网址 Flickr30k 图片描述 31,783 images,每张图片5个语句标注 链接 Microsoft COCO 图片描述 330,000 images,每张图片至少5个语句标注 链接 ESP Game 多标签定义图像 20,770 images,268 tags,诸如bed, light man,music 链接 IAPRTC-12 多标签定义图像 19,452 images,291 tags 链接 NUS-WIDE 多标签定义图像

面向小数据集构建图像分类模型Keras

文章信息 本文地址:http://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html 本文作者:Francois Chollet 概述 在本文中,我们将提供一些面向小数据集(几百张到几千张图片)构造高效.实用的图像分类器的方法. 本文将探讨如下几种方法: 从图片中直接训练一个小网络(作为基准方法) 利用预训练网络的bottleneck(瓶颈)特征 fine-tune预训练网

YOLO2解读,训练自己的数据及相关转载以供学习

https://pjreddie.com/darknet/yolo/ 具体安装及使用可以参考官方文档https://github.com/pjreddie/darknet http://blog.csdn.net/u012235274/article/details/52399425 caffe-yolo 训练http://blog.csdn.net/u012235274/article/details/52120152 caffe 版本 yolo 过程记录 YOLOv2 参数详解[net]//

【Python数据挖掘课程】四.决策树DTC数据分析及鸢尾数据集分析

今天主要讲述的内容是关于决策树的知识,主要包括以下内容:        1.分类及决策树算法介绍        2.鸢尾花卉数据集介绍        3.决策树实现鸢尾数据集分析        前文推荐:       [Python数据挖掘课程]一.安装Python及爬虫入门介绍       [Python数据挖掘课程]二.Kmeans聚类数据分析及Anaconda介绍       [Python数据挖掘课程]三.Kmeans聚类代码实现.作业及优化        希望这篇文章对你有所帮助,尤其