Machine Learning(一):基于 TensorFlow 实现宠物血统智能识别


声明:本文转载自https://my.oschina.net/zijingshanke/blog/1620373,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

人类喜欢将所有事物都纳入鄙视链的范畴,宠物当然也不例外。一般来说,拥有一只纯种宠物可以让主人占据鄙视链的云端,进而鄙视那些混血或者流浪宠物。甚至还发展出了专业的鉴定机构,可以颁发《血统证明书》。但是考究各类纯种鉴定的常规方法:例如眼睛的大小、颜色、鼻子的特点、身躯长度、尾巴特征、毛发等,当然也包括一些比较玄幻的特征:宠物家族的个性、气质等等。抛开“黑魔法”不在此讨论之外,既然是基于生物外形特征鉴定,判断是否纯种的需求本质上就是一个图像识别服务。

IMG_3560.png

Hello TensorFlow

Tensorflow is not a Machine Learning specific library, instead, is a general purpose computation library that represents computations with graphs.

TensorFlow 开源软件库(Apache 2.0 许可证),最初由 Google Brain 团队开发。TensorFlow 提供了一系列算法模型和编程接口,让我们可以快速构建一个基于机器学习的智能服务。对于开发者来说,目前有四种编程接口可供选择:

  • C++ source code: Tensorflow 核心基于 C++ 编写,支持从高到低各个层级的操作;
  • Python bindings & Python library: 对标 C++ 实现,支持 Python 调用 C++ 函数;
  • Java bindings;
  • Go binding;

下面是一个简单的实例:

环境准备

  • 安装 TensorFlow C library,包含一个头文件 c_api.h 和 libtensorflow.so
wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.5.0.tar.gz  ## options TF_TYPE="cpu" # Change to "gpu" for GPU support TF_VERSION='1.5.0' curl -L \   "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-$(go env GOOS)-x86_64-${TF_VERSION}.tar.gz" | 
go get github.com/tensorflow/tensorflow/tensorflow/go go get github.com/tensorflow/tensorflow/tensorflow/go/op 
  • 下载模型(demo model),包含一个标签文件 label_strings.txt 和 graph.pb
mkdir model wget https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip -O model/inception.zip unzip model/inception.zip -d model chmod -R 777 model 

Tensorflow Model Function

//Loading TensorFlow model func loadModel() error {   // Load inception model   model, err := ioutil.ReadFile("./model/tensorflow_inception_graph.pb")   if err != nil {     return err   }   graph = tf.NewGraph()   if err := graph.Import(model, ""); err != nil {     return err   }   // Load labels   labelsFile, err := os.Open("./model/imagenet_comp_graph_label_strings.txt")   if err != nil {     return err   }   defer labelsFile.Close()   scanner := bufio.NewScanner(labelsFile)   // Labels are separated by newlines   for scanner.Scan() {     labels = append(labels, scanner.Text())   }   if err := scanner.Err(); err != nil {     return err   }   return nil } 

Classifying Workflow

基于 Tensorflow 模型实现图像识别的主要流程如下:

  • 图像转换 (Convert to tensor )
  • 图像标准化( Normalize )
  • 图像分类 ( Classifying )
func recognizeHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {   // Read image   imageFile, header, err := r.FormFile("image")   // Will contain filename and extension   imageName := strings.Split(header.Filename, ".")   if err != nil {     responseError(w, "Could not read image", http.StatusBadRequest)     return   }   defer imageFile.Close()   var imageBuffer bytes.Buffer   // Copy image data to a buffer   io.Copy(&imageBuffer, imageFile)    // ...    tensor, err := makeTensorFromImage(&imageBuffer, imageName[:1][0])   if err != nil {     responseError(w, "Invalid image", http.StatusBadRequest)     return   }    // ... } 

函数 makeTensorFromImage() which runs an image tensor through the normalization graph.

func makeTensorFromImage(imageBuffer *bytes.Buffer, imageFormat string) (*tf.Tensor, error) {   tensor, err := tf.NewTensor(imageBuffer.String())   if err != nil {     return nil, err   }   graph, input, output, err := makeTransformImageGraph(imageFormat)   if err != nil {     return nil, err   }   session, err := tf.NewSession(graph, nil)   if err != nil {     return nil, err   }   defer session.Close()   normalized, err := session.Run(     map[tf.Output]*tf.Tensor{input: tensor},     []tf.Output{output},     nil)   if err != nil {     return nil, err   }   return normalized[0], nil } 

函数 maketransformimagegraph() 将图形的像素值调整到 224x224,以符合模型输入参数要求。

func makeTransformImageGraph(imageFormat string) (graph *tf.Graph, input, output tf.Output, err error) {   const (     H, W  = 224, 224     Mean  = float32(117)     Scale = float32(1)   )   s := op.NewScope()   input = op.Placeholder(s, tf.String)   // Decode PNG or JPEG   var decode tf.Output   if imageFormat == "png" {     decode = op.DecodePng(s, input, op.DecodePngChannels(3))   } else {     decode = op.DecodeJpeg(s, input, op.DecodeJpegChannels(3))   }   // Div and Sub perform (value-Mean)/Scale for each pixel   output = op.Div(s,     op.Sub(s,       // Resize to 224x224 with bilinear interpolation       op.ResizeBilinear(s,         // Create a batch containing a single image         op.ExpandDims(s,           // Use decoded pixel values           op.Cast(s, decode, tf.Float),           op.Const(s.SubScope("make_batch"), int32(0))),         op.Const(s.SubScope("size"), []int32{H, W})),       op.Const(s.SubScope("mean"), Mean)),     op.Const(s.SubScope("scale"), Scale))   graph, err = s.Finalize()   return graph, input, output, err } 

最后,将格式化的 image tensor 输入到 Inception model graph 中运算。

session, err := tf.NewSession(graph, nil) if err != nil {   log.Fatal(err) } defer session.Close() output, err := session.Run(   map[tf.Output]*tf.Tensor{     graph.Operation("input").Output(0): tensor,   },   []tf.Output{     graph.Operation("output").Output(0),   },   nil) if err != nil {   responseError(w, "Could not run inference", http.StatusInternalServerError)   return } 

Testing

func main() {   if err := loadModel(); err != nil {     log.Fatal(err)     return   }   r := httprouter.New()   r.POST("/recognize", recognizeHandler)   err := http.ListenAndServe(":8080", r)   if err != nil {     log.Println(err)     return   } } 

识别案例:黑天鹅

$ curl localhost:8080/recognize -F 'image=@../data/IMG_3560.png' {   "filename":"IMG_3000.png",   "labels":[     {"label":"black swan","probability":0.98746836,"Percent":"98.75%"},     {"label":"oystercatcher","probability":0.0040768473,"Percent":"0.41%"},     {"label":"American coot","probability":0.002185003,"Percent":"0.22%"},     {"label":"black stork","probability":0.0011524856,"Percent":"0.12%"},     {"label":"redshank","probability":0.0010183558,"Percent":"0.10%"}] } 

IMG_3560.png

IMG_3608.png

通过上面的案例我们可以发现,这个服务目前可以对于黑天鹅图像的推算概率值为 98.75%,非常准确;但是对于另外两张宠物狗的图像,最高的推算概率值也仅有 30% 左右,虽然也没有被识别成猫咪或者狼,但是和理想效果要求可用性还有一段距离(此处暂时忽略物种本身的复杂性)。主要是因为现在我们使用的还只是一个非常“原始”的模型,如果需要为小众领域服务(宠物,也可以是其它事物),需要通过训练(Training Models)增强优化,或者引入更丰富的标签,更合适的模型。当然,训练过程中也会存在样本质量不佳的情况,错误样本和各种噪音也会影响准确度。

更多精彩内容扫码关注公众号:RiboseYim's Blog 微信公众号

本文发表于2018年02月09日 10:31
(c)注:本文转载自https://my.oschina.net/zijingshanke/blog/1620373,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1719 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1