一、概述

这次要解决的问题是输入一张照片,输出人物的颜值数据。

学习样本来源于华南理工大学发布的SCUT-FBP5500数据集,数据集包括 5500 人,每人按颜值魅力打分,分值在 1 到 5 分之间。其中包括男性、女性、中国人、外国人四个分类。

SCUT-FBP5500_full.csv文件标记了每个图片人物的颜值打分数据。(我把分值一项乘以了20,变成了满分100分,不影响计算结果)

整个程序处理流程和前一篇图片分类的基本一致,唯一的区别,分类用的是多元分类算法,这次采用的是回归算法。

二、源码

下面是全部代码:

namespace TensorFlow_ImageClassification
{ class Program
{
//Assets files download from:https://gitee.com/seabluescn/ML_Assets
static readonly string AssetsFolder = @"D:\StepByStep\Blogs\ML_Assets";
static readonly string TrainDataFolder = Path.Combine(AssetsFolder, "FaceValueDetection", "SCUT-FBP5500");
static readonly string TrainTagsPath = Path.Combine(AssetsFolder, "FaceValueDetection", "SCUT-FBP5500_asia_full.csv");
static readonly string TestDataFolder = Path.Combine(AssetsFolder, "FaceValueDetection", "testimages");
static readonly string inceptionPb = Path.Combine(AssetsFolder, "TensorFlow", "tensorflow_inception_graph.pb");
static readonly string imageClassifierZip = Path.Combine(Environment.CurrentDirectory, "MLModel", "imageClassifier.zip"); //配置用常量
private struct ImageNetSettings
{
public const int imageHeight = ;
public const int imageWidth = ;
public const float mean = ;
public const float scale = ;
public const bool channelsLast = true;
} static void Main(string[] args)
{
TrainAndSaveModel();
LoadAndPrediction(); Console.WriteLine("Hit any key to finish the app");
Console.ReadKey();
} public static void TrainAndSaveModel()
{
MLContext mlContext = new MLContext(seed: ); // STEP 1: 准备数据
var fulldata = mlContext.Data.LoadFromTextFile<ImageNetData>(path: TrainTagsPath, separatorChar: ',', hasHeader: true);
var trainTestData = mlContext.Data.TrainTestSplit(fulldata, testFraction: 0.2);
var trainData = trainTestData.TrainSet;
var testData = trainTestData.TestSet; // STEP 2:创建学习管道
var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: TrainDataFolder, inputColumnName: nameof(ImageNetData.ImagePath))
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input"))
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean))
.Append(mlContext.Model.LoadTensorFlowModel(inceptionPb).
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
.Append(mlContext.Regression.Trainers.LbfgsPoissonRegression(labelColumnName: "Label", featureColumnName: "softmax2_pre_activation")); // STEP 3:通过训练数据调整模型
ITransformer model = pipeline.Fit(trainData); // STEP 4:评估模型
var predictions = model.Transform(testData);
var metrics = mlContext.Regression.Evaluate(predictions, labelColumnName: "Label", scoreColumnName: "Score");
PrintRegressionMetrics( metrics); //STEP 5:保存模型
Console.WriteLine("====== Save model to local file =========");
mlContext.Model.Save(model, trainData.Schema, imageClassifierZip);
} static void LoadAndPrediction()
{
MLContext mlContext = new MLContext(seed: ); // Load the model
ITransformer loadedModel = mlContext.Model.Load(imageClassifierZip, out var modelInputSchema); // Make prediction function (input = ImageNetData, output = ImageNetPrediction)
var predictor = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(loadedModel); DirectoryInfo testdir = new DirectoryInfo(TestDataFolder);
foreach (var jpgfile in testdir.GetFiles("*.jpg"))
{
ImageNetData image = new ImageNetData();
image.ImagePath = jpgfile.FullName;
var pred = predictor.Predict(image); Console.WriteLine($"Filename:{jpgfile.Name}:\tPredict Result:{pred.FaceValue}");
}
}
} public class ImageNetData
{
[LoadColumn()]
public string ImagePath; [LoadColumn()]
public float Label;
} public class ImageNetPrediction
{
[ColumnName("Score")]
public float FaceValue;
}
}

三、分析

1、数据处理通道

// STEP 2:创建学习管道
var pipeline = mlContext.Transforms.LoadImages(...)
.Append(mlContext.Transforms.ResizeImages(...)
.Append(mlContext.Transforms.ExtractPixels(...)
.Append(mlContext.Model.LoadTensorFlowModel(inceptionPb)
.ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
.Append(mlContext.Regression.Trainers.LbfgsPoissonRegression(labelColumnName: "Label", featureColumnName: "softmax2_pre_activation"));

LoadImages、ResizeImages、ExtractPixels:上篇文章都已经介绍过了;

ScoreTensorFlowModel方法把图片像素值转换为图片特征数据,并存储在softmax2_pre_activation列,Label列保存的是颜值数据,通过回归算法形成模型,当输入新的特征数据时就可以得出对应的颜值数据。

算法采用的是:L-BFGS Poisson Regression (拟牛顿法泊松回归)

 

2、预测结果

在网上找了一些大头照,通过程序进行预测,右侧是预测结果:

预测结果虽然和我认为的不完全一致,但总体上可以接受,大方向没什么问题,存在偏差主要有以下几个因素:

1、学习样本的客观性存疑,其打分数据可能是分配给多人打分后汇总的,每个人标准不一致;

2、被检测图片不是很规范,如尺寸、比例、背景、使用美颜软件等;

3、颜值本身就不具备客观性,不存在标准答案,如果我说林心如比如花漂亮,大家肯定都同意,但我如果说古力娜扎比迪丽热巴漂亮,肯定有人不赞成。

四、资源获取 

源码下载地址:https://github.com/seabluescn/Study_ML.NET

工程名称:TensorFlow_FaceValueDetection

资源获取:https://gitee.com/seabluescn/ML_Assets (SCUT-FBP5500)

点击查看机器学习框架ML.NET学习笔记系列文章目录

机器学习框架ML.NET学习笔记【7】人物图片颜值判断的更多相关文章

  1. 机器学习框架ML.NET学习笔记【4】多元分类之手写数字识别

    一.问题与解决方案 通过多元分类算法进行手写数字识别,手写数字的图片分辨率为8*8的灰度图片.已经预先进行过处理,读取了各像素点的灰度值,并进行了标记. 其中第0列是序号(不参与运算).1-64列是像 ...

  2. 机器学习框架ML.NET学习笔记【1】基本概念与系列文章目录

    一.序言 微软的机器学习框架于2018年5月出了0.1版本,2019年5月发布1.0版本.期间各版本之间差异(包括命名空间.方法等)还是比较大的,随着1.0版发布,应该是趋于稳定了.之前在园子里也看到 ...

  3. 机器学习框架ML.NET学习笔记【3】文本特征分析

    一.要解决的问题 问题:常常一些单位或组织召开会议时需要录入会议记录,我们需要通过机器学习对用户输入的文本内容进行自动评判,合格或不合格.(同样的问题还类似垃圾短信检测.工作日志质量分析等.) 处理思 ...

  4. 机器学习框架ML.NET学习笔记【2】入门之二元分类

    一.准备样本 接上一篇文章提到的问题:根据一个人的身高.体重来判断一个人的身材是否很好.但我手上没有样本数据,只能伪造一批数据了,伪造的数据比较标准,用来学习还是蛮合适的. 下面是我用来伪造数据的代码 ...

  5. 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)

    一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...

  6. 机器学习框架ML.NET学习笔记【6】TensorFlow图片分类

    一.概述 通过之前两篇文章的学习,我们应该已经了解了多元分类的工作原理,图片的分类其流程和之前完全一致,其中最核心的问题就是特征的提取,只要完成特征提取,分类算法就很好处理了,具体流程如下: 之前介绍 ...

  7. 机器学习框架ML.NET学习笔记【8】目标检测(采用YOLO2模型)

    一.概述 本篇文章介绍通过YOLO模型进行目标识别的应用,原始代码来源于:https://github.com/dotnet/machinelearning-samples 实现的功能是输入一张图片, ...

  8. 机器学习框架ML.NET学习笔记【9】自动学习

    一.概述 本篇我们首先通过回归算法实现一个葡萄酒品质预测的程序,然后通过AutoML的方法再重新实现,通过对比两种实现方式来学习AutoML的应用. 首先数据集来自于竞赛网站kaggle.com的UC ...

  9. ML.NET学习笔记 ---- 系列文章

    机器学习框架ML.NET学习笔记[1]基本概念与系列文章目录 机器学习框架ML.NET学习笔记[2]入门之二元分类 机器学习框架ML.NET学习笔记[3]文本特征分析 机器学习框架ML.NET学习笔记 ...

随机推荐

  1. numpy中的tile函数

    tile()函数可以很方便的生成多维数组.它有两个参数,第一个数是原始数组;第二个表示如何来生成,第一个数字表示生成几行,第二个表示每行有多少个原始数组(如果只写一个数字,那么就默认是一行). fro ...

  2. bzoj1177&p3625 [APIO2009]采油区域p[大力讨论]

    我好菜菜啊. 给定矩形,从中选出三个边长K的正方形互不重叠,使得覆盖到的数总和最大. 想的时候往dp上钻去了..结果一开始想了一个错的dp,像这样 /************************* ...

  3. 「NOIP2017」「LuoguP3959」 宝藏(爆搜

    题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nn 个深埋在地下的宝藏屋, 也给出了这 nn 个宝藏屋之间可供开发的mm 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏. ...

  4. [转]BX9054: 各浏览器对 document.execCommand 方法的首参数可选值范围存在差异

    作者:钱宝坤 标准参考 无. 问题描述 execCommand 方法通常用于控制可编辑的 IFRAME 内容,制作富文本编辑器. 但他现在为止还是非标准的,方法的首参数 Commmands 的可选值由 ...

  5. HDFS数据迁移目录到正确姿势

    添加了一块硬盘,原来的DataNode已经把原有的硬盘占满:怎么办,想要把旧有的数据迁移到新的硬盘上面: 1. 在CDH中修改目录(在HDFS组件中搜索.dir),本例中,新加的硬盘挂载在/data上 ...

  6. struts2的使用知识点

    最开始学习java的时候学习过struts,但是对配置和struts的理解深度不够,现在工作虽然再用,但是自己搭建环境和使用心得始终很零散,所以现在决定重新理一遍,有条理的学习一下struts. 至于 ...

  7. Hibernate&nbsp;Annotation&nbsp;(…

    引自:http://www.cnblogs.com/hongten/archive/2011/07/20/2111773.html 进入:http://www.hibernate.org 说明文档: ...

  8. 条款39:明智而审慎的使用private继承

    Use private inheritance judiciously. 如果classes之间的继承关系是private,编译器不会自动将一个derived class对象转换为一个base cla ...

  9. 读取web应用下的资源文件(例如properties)

    package gz.itcast.b_resource; import java.io.IOException; import java.io.InputStream; import java.ut ...

  10. js的prototype的详解(1)

    一.什么是JavaScript中对象的prototype属性 JavaScript中对象的prototype属性,是用来返回对象类型原型的引用的.我们使用prototype属性提供对象的类的一组基本功 ...