Machine Learning(一):基於 TensorFlow 實現寵物血統智能識別

  • Hello TensorFlow
  • TensorFlow C library
  • TensorFlow Go bingding

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## optionsTF_TYPE="cpu" # Change to "gpu" for GPU supportTF_VERSION=1.5.0curl -L "https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-$(go env GOOS)-x86_64-${TF_VERSION}.tar.gz" |

  • 安裝 Go 語言環境,參考:玩轉編程語言:Golang
  • 安裝 Tensorflow Go binding library

go get github.com/tensorflow/tensorflow/tensorflow/gogo get github.com/tensorflow/tensorflow/tensorflow/go/op

  • 下載模型(demo model),包含一個標籤文件 label_strings.txt 和 graph.pb

mkdir modelwget https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip -O model/inception.zipunzip model/inception.zip -d modelchmod -R 777 model

Tensorflow Model Function

//Loading TensorFlow modelfunc 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%"}]}

通過上面的案例我們可以發現,這個服務目前可以對於黑天鵝圖像的推算概率值為 98.75%,非常準確;但是對於另外兩張寵物狗的圖像,最高的推算概率值也僅有 30% 左右,雖然也沒有被識別成貓咪或者狼,但是和理想效果要求可用性還有一段距離(此處暫時忽略物種本身的複雜性)。主要是因為現在我們使用的還只是一個非常「原始」的模型,如果需要為小眾領域服務(寵物,也可以是其它事物),需要通過訓練(Training Models)增強優化,或者引入更豐富的標籤,更合適的模型。當然,訓練過程中也會存在樣本質量不佳的情況,錯誤樣本和各種噪音也會影響準確度。

Machine Learning(一):基於 TensorFlow 實現寵物血統智能識別riboseyim.github.io

Machine Learning:機器學習演算法riboseyim.github.io圖標數據可視化(三)基於 Graphviz 實現程序化繪圖riboseyim.github.io

擴展閱讀

  • How to Retrain Inceptions Final Layer for New Categories
  • PaperTensorFlow:Large-Scale Machine Learning on Heterogeneous Distributed Systems (Preliminary White Paper, November 9, 2015)
  • Getting Started with TensorFlow: A Machine Learning Tutorial
  • YoutubeIntroduction To TensorFlow
  • We Need to Go Deeper: A Practical Guide to Tensorflow and Inception
  • Tensorflow.org: Image Recognition

推薦閱讀:

把故宮裝進手機,讓柯潔走向最強!谷歌在北京秀出四個AI商用大招
使用 TensorFlow 實現神經網路
資源|100精品開源項目助你成為TensorFlow專家(一)
TensorFlow中.crf_log_likelihood()怎麼用,越具體越好?
學習筆記TF029:實現進階卷積網路

TAG:機器學習 | TensorFlow | Go編程 |