一、概述

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

学习样本来源于华南理工大学发布的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 = 224;
public const int imageWidth = 224; public const float mean = 117; public const
float scale = 1; 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: 1); // 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: 1); // 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(0)]
public string ImagePath; [LoadColumn(1)] public float Label; } public class
ImageNetPrediction { [ColumnName("Score")] public float FaceValue; } } View Code
  

三、分析

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学习笔记系列文章目录 <https://www.cnblogs.com/seabluescn/p/10904391.html>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信