学学笔记TF022:产品景况模型铺排、Docker镜像、巴

作者:编程技术

本学科旨在把三个初期被置于练习过的类型里的图纸,通过运维四个限令以识别该图像具体属于哪个品种。步骤如下图所示:

0. Google 英斯ption模型简要介绍

英斯ption为谷歌(Google)开源的CNN模型,到现在已经明白多个版本,每八个本子都以依据大型图像数据库ImageNet中的数据练习而成。由此大家得以一贯运用谷歌(Google)的英斯ption模型来完毕图像分类。本篇小说首要以英斯ption_v3模型为底蕴。英斯ption v3模型大概有2500万个参数,分类一张图像就用了50亿的乘加指令。在一台未有GPU的今世PC上,分类一张图像转眼就能够变成。

读书笔记TF022:产品情形模型铺排、Docker镜像、Bazel工作区、导出模型、服务器、顾客端,tf022docker

出品情形模型陈设,创建轻便Web APP,顾客上传图像,运维Inception模型,完成图像自动分拣。

搭建TensorFlow服务付出情状。安装Docker, 。用配备文件在地头创建Docker镜像,docker build --pull -t $USE索罗德/tensorflow-serving-devel 。镜像运维容器,docker run -v $HOME:/mnt/home -p 9999:9999 -it $USEENCORE/tensorflow-serving-devel ,在home目录加载到容器/mnt/home路线,在终极事业。用IDE或编辑器编辑代码,用容器运营创设筑工程具,主机通过9999端口访谈,塑造服务器。exit命令退出容器终端,结束运行。

TensorFlow服务程序C 写,使用谷歌的Bazel创设工具。容器运行Bazel。巴泽l代码级管理第三方重视项。Bazel自动下载创设。项目库根目录定义WO逍客KSPACE文件。TensorFlow模型库包蕴英斯ption模型代码。

TensorFlow服务在品种作为Git子模块。mkdir ~/serving_example,cd ~/serving_example,git init,git submodule add ,tf_serving,git submodule update --init --recursive 。

WORKSPACE文件local_repository法则定义第三方重视为本土存款和储蓄文件。项目导入tf_workspace准则起先化TensorFlow信赖项。

workspace(name = "serving")

local_repository(
name = "tf_serving",
path = __workspace_dir__ "/tf_serving",
)

local_repository(
name = "org_tensorflow",
path = __workspace_dir__ "/tf_serving/tensorflow",
)

load('//tf_serving/tensorflow/tensorflow:workspace.bzl', 'tf_workspace')
tf_workspace("tf_serving/tensorflow/", "@org_tensorflow")

bind(
name = "libssl",
actual = "@boringssl_git//:ssl",
)

bind(
name = "zlib",
actual = "@zlib_archive//:zlib",
)

local_repository(
name = "inception_model",
path = __workspace_dir__ "/tf_serving/tf_models/inception",
)

导出演练好的模子,导出数据流图及变量,给产品用。模型数据流图,必需从占位符接收输入,单步估量计算输出。英斯ption模型(或一般图像识别模型),JPEG编码图像字符串输入,与从TFRecord文件读取输入差别。定义输入占位符,调用函数转变占位符表示外界输入为原来猜度模型输入格式,图像字符串转变为各分量位于[0, 1]内像素张量,缩放图像尺寸,符合模型期望宽度中度,像素值调换成模型供给区间[-1, 1]内。调用原始模型测算方法,依附调换输入臆想结果。

测算方法各参数赋值。从检查点恢复参数值。周期性保存模型练习检查点文件,文件包涵学习参数。最终三遍保存练习检查点文件包罗最后更新模型参数。下去载预陶冶检查点文件: 。在Docker容器中,cd /tmp, curl -0 , tar -xzf inception-v3-2016-03-01.tar.gz 。

tensorflow_serving.session_bundle.exporter.Exporter类导出模型。传入保存器实例成立实例,用exporter.classification_signature创立模型签字。钦命input_tensor、输出张量。classes_tensor 包括输出类名称列表、模型分配各体系分值(或可能率)socres_tensor。连串数多模子,配置钦点仅返田大口tf.nntop_k选择体系,模型分配分数降序排列前K个种类。调用exporter.Exporter.init方法签字,export方法导出模型,接收输出路线、模型版本号、会话对象。Exporter类自动生成代码存在依附,Doker容器内部采纳中bazel运转导出器。代码保存到bazel工作区exporter.py。

import time
import sys

import tensorflow as tf
from tensorflow_serving.session_bundle import exporter
from inception import inception_model

NUM_CLASSES_TO_RETURN = 10

def convert_external_inputs(external_x):
image = tf.image.convert_image_dtype(tf.image.decode_jpeg(external_x, channels=3), tf.float32)
images = tf.image.resize_bilinear(tf.expand_dims(image, 0), [299, 299])
images = tf.mul(tf.sub(images, 0.5), 2)
return images

def inference(images):
logits, _ = inception_model.inference(images, 1001)
return logits

external_x = tf.placeholder(tf.string)
x = convert_external_inputs(external_x)
y = inference(x)

saver = tf.train.Saver()

with tf.Session() as sess:
ckpt = tf.train.get_checkpoint_state(sys.argv[1])
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, sys.argv[1] "/" ckpt.model_checkpoint_path)
else:
print("Checkpoint file not found")
raise SystemExit

scores, class_ids = tf.nn.top_k(y, NUM_CLASSES_TO_RETURN)

classes = tf.contrib.lookup.index_to_string(tf.to_int64(class_ids),
mapping=tf.constant([str(i) for i in range(1001)]))

model_exporter = exporter.Exporter(saver)
signature = exporter.classification_signature(
input_tensor=external_x, classes_tensor=classes, scores_tensor=scores)
model_exporter.init(default_graph_signature=signature, init_op=tf.initialize_all_tables())
model_exporter.export(sys.argv[1] "/export", tf.constant(time.time()), sess)

一个创设法规BUILD文件。在容器命令运营导出器,cd /mnt/home/serving_example, hazel run:export /tmp/inception-v3 ,依靠/tmp/inception-v3涉及的检查点文件在/tmp/inception-v3/{currenttimestamp}/创制导出器。第一遍运维要对TensorFlow编写翻译。load从表面导入protobuf库,导入cc_proto_library准则定义,为proto文件定义构建准则。通过命令bazel run :server 9999 /tmp/inception-v3/export/{timestamp},容器运营臆度服务器。

py_binary(
name = "export",
srcs = [
"export.py",
],
deps = [
"@tf_serving//tensorflow_serving/session_bundle:exporter",
"@org_tensorflow//tensorflow:tensorflow_py",
"@inception_model//inception",
],
)

load("@protobuf//:protobuf.bzl", "cc_proto_library")

cc_proto_library(
name="classification_service_proto",
srcs=["classification_service.proto"],
cc_libs = ["@protobuf//:protobuf"],
protoc="@protobuf//:protoc",
default_runtime="@protobuf//:protobuf",
use_grpc_plugin=1
)

cc_binary(
name = "server",
srcs = [
"server.cc",
],
deps = [
":classification_service_proto",
"@tf_serving//tensorflow_serving/servables/tensorflow:session_bundle_factory",
"@grpc//:grpc ",
],
)

概念服务器接口。TensorFlow服务应用gRPC合同(基于HTTP/2二进制左券)。协理成立服务器和自动生成客商端存根各类语言。在protocol buffer定义服务公约,用于gRPC IDL(接口定义语言)和二进制编码。接收JPEG编码待分类图像字符串输入,再次回到分数排列预计体系列表。定义在classification_service.proto文件。接收图像、音频片段、文字服务可用可一接口。proto编写翻译器调换proto文件为顾客端和劳务器类定义。bazel build:classification_service_proto可行创设,通过bazel-genfiles/classification_service.grpc.pb.h检查结果。猜想逻辑,ClassificationService::瑟维斯接口必须完结。检查bazel-genfiles/classification_service.pb.h查看request、response音讯定义。proto定义造成每体系型C 接口。

syntax = "proto3";

message ClassificationRequest {
// bytes input = 1;
float petalWidth = 1;
float petalHeight = 2;
float sepalWidth = 3;
float sepalHeight = 4;
};

message ClassificationResponse {
repeated ClassificationClass classes = 1;
};

message ClassificationClass {
string name = 1;
float score = 2;
}

service ClassificationService {
rpc classify(ClassificationRequest) returns (ClassificationResponse);
}

兑现预计服务器。加载导出模型,调用测度方法,达成ClassificationService::Service。导出模型,成立SessionBundle对象,包蕴完全加载数据流图TF会话对象,定义导出工具分类签字元数据。SessionBundleFactory类创制SessionBundle对象,配置为pathToExportFiles钦点路径加载导出模型,再次来到创造SessionBundle实例unique指针。定义ClassificationServiceImpl,接收SessionBundle实例参数。

加载分类具名,GetClassificationSignature函数加载模型导出元数据ClassificationSignature,签字钦命所吸收接纳图像真实名称的输入张量逻辑名称,以及数额流图输出张量逻辑名称映射估摸结果。将protobuf输入转变为推断输入张量,request参数复制JPEG编码图像字符串到猜想张量。运营估量,sessionbundle得到TF会话对象,运维三次,传入输入输出张量推测。估摸输出张量转变protobuf输出,输出张量结果复制到ClassificationResponse音讯内定形状response输出参数格式化。设置gRPC服务器,SessionBundle对象配置,创制ClassificationServiceImpl实例样板代码。

#include <iostream>
#include <memory>
#include <string>

#include <grpc /grpc .h>

#include "classification_service.grpc.pb.h"

#include "tensorflow_serving/servables/tensorflow/session_bundle_factory.h"

using namespace std;
using namespace tensorflow::serving;
using namespace grpc;

unique_ptr<SessionBundle> createSessionBundle(const string& pathToExportFiles) {
SessionBundleConfig session_bundle_config = SessionBundleConfig();
unique_ptr<SessionBundleFactory> bundle_factory;
SessionBundleFactory::Create(session_bundle_config, &bundle_factory);

unique_ptr<SessionBundle> sessionBundle;
bundle_factory->CreateSessionBundle(pathToExportFiles, &sessionBundle);

return sessionBundle;
}

class ClassificationServiceImpl final : public ClassificationService::Service {

private:
unique_ptr<SessionBundle> sessionBundle;

public:
ClassificationServiceImpl(unique_ptr<SessionBundle> sessionBundle) :
sessionBundle(move(sessionBundle)) {};

Status classify(ServerContext* context, const ClassificationRequest* request,
ClassificationResponse* response) override {

ClassificationSignature signature;
const tensorflow::Status signatureStatus =
GetClassificationSignature(sessionBundle->meta_graph_def, &signature);

if (!signatureStatus.ok()) {
return Status(StatusCode::INTERNAL, signatureStatus.error_message());
}

tensorflow::Tensor input(tensorflow::DT_STRING, tensorflow::TensorShape());
input.scalar<string>()() = request->input();

vector<tensorflow::Tensor> outputs;

const tensorflow::Status inferenceStatus = sessionBundle->session->Run(
{{signature.input().tensor_name(), input}},
{signature.classes().tensor_name(), signature.scores().tensor_name()},
{},
&outputs);

if (!inferenceStatus.ok()) {
return Status(StatusCode::INTERNAL, inferenceStatus.error_message());
}

for (int i = 0; i < outputs[0].NumElements(); i) {
ClassificationClass *classificationClass = response->add_classes();
classificationClass->set_name(outputs[0].flat<string>()(i));
classificationClass->set_score(outputs[1].flat<float>()(i));
}

return Status::OK;

}
};

int main(int argc, char** argv) {

if (argc < 3) {
cerr << "Usage: server <port> /path/to/export/files" << endl;
return 1;
}

const string serverAddress(string("0.0.0.0:") argv[1]);
const string pathToExportFiles(argv[2]);

unique_ptr<SessionBundle> sessionBundle = createSessionBundle(pathToExportFiles);

ClassificationServiceImpl classificationServiceImpl(move(sessionBundle));

ServerBuilder builder;
builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
builder.RegisterService(&classificationServiceImpl);

unique_ptr<Server> server = builder.BuildAndStart();
cout << "Server listening on " << serverAddress << endl;

server->Wait();

return 0;
}

透过劳务器端组件从webapp访谈估量服务。运维Python protocol buffer编写翻译器,生成ClassificationService Python protocol buffer顾客端:pip install grpcio cython grpcio-tools, python -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. classification_service.proto。生成包涵调用服务stub classification_service_pb2.py 。服务器收到POST须求,深入分析发送表单,创制ClassificationRequest对象 。分类服务器设置八个channel,必要提交,分类响应渲染HTML,送回客商。容器外界命令python client.py,运营服务器。浏览器导航 访问UI。

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import cgi
import classification_service_pb2
from grpc.beta import implementations

class ClientApp(BaseHTTPRequestHandler):
def do_GET(self):
self.respond_form()

def respond_form(self, response=""):

form = """
<html><body>
<h1>Image classification service</h1>
<form enctype="multipart/form-data" method="post">
<div>Image: <input type="file" name="file" accept="image/jpeg"></div>
<div><input type="submit" value="Upload"></div>
</form>
%s
</body></html>
"""

response = form % response

self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(response))
self.end_headers()
self.wfile.write(response)

def do_POST(self):

form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={
'REQUEST_METHOD': 'POST',
'CONTENT_TYPE': self.headers['Content-Type'],
})

request = classification_service_pb2.ClassificationRequest()
request.input = form['file'].file.read()

channel = implementations.insecure_channel("127.0.0.1", 9999)
stub = classification_service_pb2.beta_create_ClassificationService_stub(channel)
response = stub.classify(request, 10) # 10 secs timeout

self.respond_form("<div>Response: %s</div>" % response)

if __name__ == '__main__':
host_port = ('0.0.0.0', 8080)
print "Serving in %s:%s" % host_port
HTTPServer(host_port, ClientApp).serve_forever()

出品策动,分类服务器应用产品。编译服务器文件复制到容器永远地点,清理全数有的时候营造文件。容器中,mkdir /opt/classification_server, cd /mnt/home/serving_example, cp -R bazel-bin/. /opt/classification_server, bazel clean 。容器外界,状态提交新Docker镜像,创立记录设想文件系统变化快速照相。容器外,docker ps, dock commit <container id>。图像推送到温馨偏幸docker服务云,服务。

参照他事他说加以考察资料:
《面向机器智能的TensorFlow实施》

应接付费咨询(150元每小时),笔者的微信:qingxingfengzi

产品情况模型安插,创设简单Web APP,客户...

tulips (score = 0.00289)

3. 准备干活

不论从网络下载一张图片,命名称为husky.jpg:

husky.jpg

上面包车型客车代码就将选拔英斯ption_v3模型对那张哈士奇图片进行分拣。

首先,在所选的平台上安装Docker。

6.1 使用png只怕其余图片格式,取代jpg作为输入

The shipped InceptionV3 graph used in classify_image.py only supports JPEG images out-of-the-box. There are two ways you could use this graph with PNG images:

  1. Convert the PNG image to a height
    x width x 3 (channels) Numpy array, for example using PIL, then feed the 'DecodeJpeg:0' tensor:
import numpy as np
from PIL import Image
# ...

image = Image.open("example.png")
image_array = np.array(image)[:, :, 0:3]  # Select RGB channels only.

prediction = sess.run(softmax_tensor, {'DecodeJpeg:0': image_array})

Perhaps confusingly, 'DecodeJpeg:0' is the output of the DecodeJpeg op, so by feeding this tensor, you are able to feed raw image data.

  1. Add a tf.image.decode_png() op to the imported graph. Simply switching the name of the fed tensor from 'DecodeJpeg/contents:0'
    to 'DecodePng/contents:0' does not work because there is no 'DecodePng' op in the shipped graph. You can add such a node to the graph by using the input_map argument to tf.import_graph_def() :
png_data = tf.placeholder(tf.string, shape=[])
decoded_png = tf.image.decode_png(png_data, channels=3)
# ...

graph_def = ...
softmax_tensor = tf.import_graph_def(
    graph_def,
    input_map={'DecodeJpeg:0': decoded_png},
    return_elements=['softmax:0'])

sess.run(softmax_tensor, {png_data: ...})
  1. The following code should handle of both cases.
import numpy as np
from PIL import Image

image_file = 'test.jpeg'
with tf.Session() as sess:

    #     softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
    if image_file.lower().endswith('.jpeg'):
        image_data = tf.gfile.FastGFile(image_file, 'rb').read()
        prediction = sess.run('final_result:0', {'DecodeJpeg/contents:0': image_data})
    elif image_file.lower().endswith('.png'):
        image = Image.open(image_file)
        image_array = np.array(image)[:, :, 0:3]
        prediction = sess.run('final_result:0', {'DecodeJpeg:0': image_array})

    prediction = prediction[0]    
    print(prediction)

or shorter version with direct strings:

image_file = 'test.png' # or 'test.jpeg'
image_data = tf.gfile.FastGFile(image_file, 'rb').read()
ph = tf.placeholder(tf.string, shape=[])

with tf.Session() as sess:        
    predictions = sess.run(output_layer_name, {ph: image_data} )

mv flower_photos.tgz local/

1. Google Inception模型发展

以下为英斯ption四个版本所对应的散文,末尾为ILSVRC中的Top-5错误率:

  • [v1] Going Deeper with Convolutions: 6.67% test error
  • [v2] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift: 4.8% test error
  • [v3] Rethinking the Inception Architecture for Computer Vision: 3.5% test error
  • [v4] Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning: 3.08% test error

正文由Ali云云栖社区团协会翻译。

4. 代码

先创制二个类NodeLookup来将softmax概率值映射到标签上;然后创制八个函数create_graph()来读取并新建立模型型;最终读取哈士奇图片实行归类识别:

# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
#import re
import os

model_dir='C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/Inception_model'
image = 'C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/Images/husky.jpg'


#将类别ID转换为人类易读的标签
class NodeLookup(object):
    def __init__(self, label_lookup_path=None, uid_lookup_path=None):
        if not label_lookup_path:
            # 加载“label_lookup_path”文件
            # 此文件将数据集中所含类别(1-1000)与一个叫做target_class_string的地址对应起来
            # 其地址编码为“n********”星号代表数字
            label_lookup_path = os.path.join(
                    model_dir, 'imagenet_2012_challenge_label_map_proto.pbtxt')
        if not uid_lookup_path:
            # 加载“uid_lookup_path”文件
            # 此文件将数据集中所含类别具体名称与编码方式为“n********”的地址/UID一一对应起来
            uid_lookup_path = os.path.join(
                    model_dir, 'imagenet_synset_to_human_label_map.txt')
        self.node_lookup = self.load(label_lookup_path, uid_lookup_path)

    def load(self, label_lookup_path, uid_lookup_path):
        if not tf.gfile.Exists(uid_lookup_path):
            # 预先检测地址是否存在
            tf.logging.fatal('File does not exist %s', uid_lookup_path)
        if not tf.gfile.Exists(label_lookup_path):
            # 预先检测地址是否存在
            tf.logging.fatal('File does not exist %s', label_lookup_path)


        # Loads mapping from string UID to human-readable string
        # 加载编号字符串n********,即UID与分类名称之间的映射关系(字典):uid_to_human

        # 读取uid_lookup_path中所有的lines
        # readlines(): Returns all lines from the file in a list.
        # Leaves the 'n' at the end.
        proto_as_ascii_lines = tf.gfile.GFile(uid_lookup_path).readlines()

        # 创建空字典uid_to_human用以存储映射关系
        uid_to_human = {}
# =============================================================================
#         # 使用正则化方法处理文件:
#         p = re.compile(r'[nd]*[ S,]*')
#         for line in proto_as_ascii_lines:         
#              = p.findall(line)
#             uid = parsed_items[0]
#             human_string = parsed_items[2]
#             uid_to_human[uid] = human_string
# =============================================================================
        # 使用简单方法处理文件:
        # 一行行读取数据
        for line in proto_as_ascii_lines:
            # 去掉换行符
            line = line.strip('n')
            # 按照‘t’分割,即tab,将line分为两个部分
            parse_items = line.split('t')
            # 获取分类编码,即UID
            uid = parse_items[0]
            # 获取分类名称
            human_string = parse_items[1]
            # 新建编号字符串n********,即UID与分类名称之间的映射关系(字典):uid_to_human
            uid_to_human[uid] = human_string


        # Loads mapping from string UID to integer node ID.
        # 加载编号字符串n********,即UID与分类代号,即node ID之间的映射关系(字典)

        # 加载分类字符串n********,即UID对应分类编号1-1000的文件
        proto_as_ascii = tf.gfile.GFile(label_lookup_path).readlines()
        # 创建空字典node_id_to_uid用以存储分类代码node ID与UID之间的关系
        node_id_to_uid = {}
        for line in proto_as_ascii:
            # 注意空格
            if line.startswith('  target_class:'):
                # 获取分类编号
                target_class = int(line.split(': ')[1])
            if line.startswith('  target_class_string:'):
                # 获取UID(带双引号,eg:"n01484850")
                target_class_string = line.split(': ')[1]
                # 去掉前后的双引号,构建映射关系
                node_id_to_uid[target_class] = target_class_string[1:-2]

        # Loads the final mapping of integer node ID to human-readable string
        # 加载node ID与分类名称之间的映射关系
        node_id_to_name = {}
        for key, val in node_id_to_uid.items():
            # 假如uid不存在于uid_to_human中,则报错
            if val not in uid_to_human:
                tf.logging.fatal('Failed to locate: %s', val)
            # 获取分类名称
            name = uid_to_human[val]
            # 构建分类编号1-1000对应分类名称的映射关系:key为node_id;val为name
            node_id_to_name[key] = name

        return node_id_to_name

    # 传入分类编号1-1000,返回分类具体名称
    def id_to_string(self, node_id):
        # 若不存在,则返回空字符串
        if node_id not in self.node_lookup:
            return ''
        return self.node_lookup[node_id]

# 读取并创建一个图graph来存放Google训练好的Inception_v3模型(函数)
def create_graph():
    with tf.gfile.FastGFile(os.path.join(
            model_dir, 'classify_image_graph_def.pb'), 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        tf.import_graph_def(graph_def, name='')

#读取图片
image_data = tf.gfile.FastGFile(image, 'rb').read()

#创建graph
create_graph()

# 创建会话,因为是从已有的Inception_v3模型中恢复,所以无需初始化
with tf.Session() as sess:
    # Inception_v3模型的最后一层softmax的输出
    # 形如'conv1'是节点名称,而'conv1:0'是张量名称,表示节点的第一个输出张量
    softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
    # 输入图像(jpg格式)数据,得到softmax概率值(一个shape=(1,1008)的向量)
    predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
    # 将结果转为1维数据
    predictions = np.squeeze(predictions)
    # 新建类:ID --> English string label.
    node_lookup = NodeLookup()
    # 排序,取出前5个概率最大的值(top-5)
    # argsort()返回的是数组值从小到大排列所对应的索引值
    top_5 = predictions.argsort()[-5:][::-1]
    for node_id in top_5:
        # 获取分类名称
        human_string = node_lookup.id_to_string(node_id)
        # 获取该分类的置信度
        score = predictions[node_id]
        print('%s (score = %.5f)' % (human_string, score))

最终输出:

runfile('C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/test.py', wdir='C:/Users/Dexter/Documents/ML_files/171003_Inception_v3')
Siberian husky (score = 0.51033)
Eskimo dog, husky (score = 0.41048)
malamute, malemute, Alaskan malamute (score = 0.00653)
kelpie (score = 0.00136)
dogsled, dog sled, dog sleigh (score = 0.00133)

有一些修改一下代码,使输入为多张图纸,输出为图片路线 图片 预测结果:

# -*- coding: utf-8 -*-
"""
Created on Fri Oct  6 19:32:04 2017
test2:将test中输入一张图片变为输入一个文件夹的图片,并使输出可见
@author: Dexter
"""

import tensorflow as tf
import numpy as np
#import re
import os
from PIL import Image
import matplotlib.pyplot as plt

model_dir='C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/Inception_model'
image = 'C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/Images/'


#将类别ID转换为人类易读的标签
class NodeLookup(object):
    def __init__(self, label_lookup_path=None, uid_lookup_path=None):
        if not label_lookup_path:
            # 加载“label_lookup_path”文件
            # 此文件将数据集中所含类别(1-1000)与一个叫做target_class_string的地址对应起来
            # 其地址编码为“n********”星号代表数字
            label_lookup_path = os.path.join(
                    model_dir, 'imagenet_2012_challenge_label_map_proto.pbtxt')
        if not uid_lookup_path:
            # 加载“uid_lookup_path”文件
            # 此文件将数据集中所含类别具体名称与编码方式为“n********”的地址/UID一一对应起来
            uid_lookup_path = os.path.join(
                    model_dir, 'imagenet_synset_to_human_label_map.txt')
        self.node_lookup = self.load(label_lookup_path, uid_lookup_path)

    def load(self, label_lookup_path, uid_lookup_path):
        if not tf.gfile.Exists(uid_lookup_path):
            # 预先检测地址是否存在
            tf.logging.fatal('File does not exist %s', uid_lookup_path)
        if not tf.gfile.Exists(label_lookup_path):
            # 预先检测地址是否存在
            tf.logging.fatal('File does not exist %s', label_lookup_path)


        # Loads mapping from string UID to human-readable string
        # 加载编号字符串n********,即UID与分类名称之间的映射关系(字典):uid_to_human

        # 读取uid_lookup_path中所有的lines
        # readlines(): Returns all lines from the file in a list.
        # Leaves the 'n' at the end.
        proto_as_ascii_lines = tf.gfile.GFile(uid_lookup_path).readlines()

        # 创建空字典uid_to_human用以存储映射关系
        uid_to_human = {}
# =============================================================================
#         # 使用正则化方法处理文件:
#         p = re.compile(r'[nd]*[ S,]*')
#         for line in proto_as_ascii_lines:         
#              = p.findall(line)
#             uid = parsed_items[0]
#             human_string = parsed_items[2]
#             uid_to_human[uid] = human_string
# =============================================================================
        # 使用简单方法处理文件:
        # 一行行读取数据
        for line in proto_as_ascii_lines:
            # 去掉换行符
            line = line.strip('n')
            # 按照‘t’分割,即tab,将line分为两个部分
            parse_items = line.split('t')
            # 获取分类编码,即UID
            uid = parse_items[0]
            # 获取分类名称
            human_string = parse_items[1]
            # 新建编号字符串n********,即UID与分类名称之间的映射关系(字典):uid_to_human
            uid_to_human[uid] = human_string


        # Loads mapping from string UID to integer node ID.
        # 加载编号字符串n********,即UID与分类代号,即node ID之间的映射关系(字典)

        # 加载分类字符串n********,即UID对应分类编号1-1000的文件
        proto_as_ascii = tf.gfile.GFile(label_lookup_path).readlines()
        # 创建空字典node_id_to_uid用以存储分类代码node ID与UID之间的关系
        node_id_to_uid = {}
        for line in proto_as_ascii:
            # 注意空格
            if line.startswith('  target_class:'):
                # 获取分类编号
                target_class = int(line.split(': ')[1])
            if line.startswith('  target_class_string:'):
                # 获取UID(带双引号,eg:"n01484850")
                target_class_string = line.split(': ')[1]
                # 去掉前后的双引号,构建映射关系
                node_id_to_uid[target_class] = target_class_string[1:-2]

        # Loads the final mapping of integer node ID to human-readable string
        # 加载node ID与分类名称之间的映射关系
        node_id_to_name = {}
        for key, val in node_id_to_uid.items():
            # 假如uid不存在于uid_to_human中,则报错
            if val not in uid_to_human:
                tf.logging.fatal('Failed to locate: %s', val)
            # 获取分类名称
            name = uid_to_human[val]
            # 构建分类编号1-1000对应分类名称的映射关系:key为node_id;val为name
            node_id_to_name[key] = name

        return node_id_to_name

    # 传入分类编号1-1000,返回分类具体名称
    def id_to_string(self, node_id):
        # 若不存在,则返回空字符串
        if node_id not in self.node_lookup:
            return ''
        return self.node_lookup[node_id]

# 读取并创建一个图graph来存放Google训练好的Inception_v3模型(函数)
def create_graph():
    with tf.gfile.FastGFile(os.path.join(
            model_dir, 'classify_image_graph_def.pb'), 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        tf.import_graph_def(graph_def, name='')

#创建graph
create_graph()

# 创建会话,因为是从已有的Inception_v3模型中恢复,所以无需初始化
with tf.Session() as sess:
    # Inception_v3模型的最后一层softmax的输出
    softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')

    # 遍历目录
    for root, dirs, files in os.walk('images/'):
        for file in files:
            # 载入图片
            image_data = tf.gfile.FastGFile(os.path.join(root, file), 'rb').read()
            # 输入图像(jpg格式)数据,得到softmax概率值(一个shape=(1,1008)的向量)
            predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
            # 将结果转为1维数据
            predictions = np.squeeze(predictions)

            # 打印图片路径及名称
            image_path = os.path.join(root, file)
            print(image_path)
            # 显示图片
            img = Image.open(image_path)
            plt.imshow(img)
            plt.axis('off')
            plt.show()

            # 新建类:ID --> English string label.
            node_lookup = NodeLookup()
            # 排序,取出前5个概率最大的值(top-5)
            # argsort()返回的是数组值从小到大排列所对应的索引值
            top_5 = predictions.argsort()[-5:][::-1]
            for node_id in top_5:
                # 获取分类名称
                human_string = node_lookup.id_to_string(node_id)
                # 获取该分类的置信度
                score = predictions[node_id]
                print('%s (score = %.5f)' % (human_string, score))
            print()

最后输出:

runfile('C:/Users/Dexter/Documents/ML_files/171003_Inception_v3/test2.py', wdir='C:/Users/Dexter/Documents/ML_files/171003_Inception_v3')
images/dog.jpg

dingo, warrigal, warragal, Canis dingo (score = 0.46103)
Chihuahua (score = 0.05741)
Eskimo dog, husky (score = 0.04384)
dhole, Cuon alpinus (score = 0.04106)
Pembroke, Pembroke Welsh corgi (score = 0.02823)

images/husky.jpg

Siberian husky (score = 0.51033)
Eskimo dog, husky (score = 0.41048)
malamute, malemute, Alaskan malamute (score = 0.00653)
kelpie (score = 0.00136)
dogsled, dog sled, dog sleigh (score = 0.00133)

tensorflow/tensorflow:nightly /bin/bash

参照他事他说加以考察资料:
  • Tensorflow: How to get a tensor by name?

for node_id in top_k:

6. 有个别勘误

curl -O

Inception

# Feed the image_data as input to the graph and get first prediction

7. 参考资料

  1. TensorFlow 教程 #07 - Inception 模型
  2. 『TensorFlow』迁移学习_他山之石,能够攻玉
  3. 『TensorFlow』迁移学习_他山之石,能够攻玉_V2
  4. 选择inception-v3做各个图像的鉴定识别

•分类:在新的图像上选取模型。举例,输入:IMG207.JPG,输出:雏菊。那一个手续快速轻易,且度量的代价小。

2. 下载Inception_v3模型

  • Inception_v3模型源码下载
    当然,要想本人开班陶冶两个英斯ption_v3模型是可以的,但费时费劲,不供给。当然,在已经练习好的英斯ption_v3模型上修修改改retrain是未曾难点的,具体就要继续文中提到。
  • models/imagenet/classify_image.py
    官方已经刑释了例程,也能够平素阅读官方代码。
  • 【下载】已陶冶好的英斯ption_v3模型(百度网盘)
  • 【下载】已磨练好的英斯ption_v3模型(官方)
    上述多少个链接都是足以使用的。

解压下载好的压缩文件,如下:

文本列表

  • classify_image_graph_def.pb文件为Inception_v3本体
  • imagenet_2012_challenge_label_map_proto.pbtxt文件内容如下所示:

    imagenet_2012_challenge_label_map_proto.pbtxt

    包含target_class与target_class_string,前边二个为分类代码,从1~1000,共1k类,记为Node_ID;前者为一编号字符串“n********”,能够知道为“地址”恐怕“桥梁”,记为UID。

  • imagenet_synset_to_human_label_map.txt文件内容如下:

    imagenet_synset_to_human_label_map.txt

    蕴含UID与品种的照射,那体系型文字标签记为human_string。

score = predictions[0][node_id]

参考资料:
  • How to retrain inception-v1 model?
  • Feeding image data in tensorflow for transfer learning

采纳TensorFlow,你能够获得具有强有力力量的眼花缭乱成效,其有力的基业来自于TensorFlow的易用性。

5. 息息相关函数补充表达

  • tf.get_default_graph()
    回去当前历程中的暗许图(能够行使Graph.as_default()设置)

Returns the default graph for the current thread.
The returned graph will be the innermost graph on which a Graph.as_default() context has been entered, or a global default graph if none has been explicitly created.
NOTE: The default graph is a property of the current thread. If you create a new thread, and wish to use the default graph in that thread, you must explicitly add a with g.as_default(): in that thread's function.

Returns:
The default Graph being used in the current thread.


  • tf.Graph.as_default()
    将Graph设置为私下认可图

Returns a context manager that makes this Graph the default graph.


  • tf.Graph.get_tensor_by_name()

All tensors have string names which you can see as follows:

[tensor.name for tensor in tf.get_default_graph().as_graph_def().node]

Once you know the name you can fetch the Tensor using <name>:0 (0 refers to endpoint which is somewhat redundant)

import tensorflow as tf

c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
e = tf.matmul(c, d, name='example')

with tf.Session() as sess:
    test = sess.run(e)
    print (e.name)  
    #example:0
    #<name>:0 (0 refers to endpoint which is somewhat redundant)
    test = tf.get_default_graph().get_tensor_by_name("example:0")
    print (test)    
    #Tensor("example:0", shape=(2, 2), dtype=float32)

graph_path = 'output_graph.pb'

--rm 退出时令docker删除容器

softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')

更多详细音讯,请点击这里查阅classify.py的事无巨细表达。

乘势retrain.py 的运维,训练图像会自行的分批次练习、测量检验和表达数据集。

label_lines = [line.rstrip() for line

这声明我们曾经获得了一个模型:给定一张图像,14回中有9次可科学猜出是七种植花朵朵类型中的哪一类。由于提供给磨练进程的放肆数不一致,分类的准确度也许有所差别。

在容器中运作下述命令,对磨练多少进行下载和完整性检查。

最终,起初读书!运转再操练脚本。

分分快三计划 1

daisy (score = 0.20722)

为了测量检验你本身的图像,保存在local目录下并取名叫test.jpg,运转 python classify.py test.jpg。输出结果如下:

上边是命令分析:

tensorflow/tensorflow:nightly从Docker Hub 运行tensorflow/tensorflow的nightly 图像,并非风尚的图像(默以为眼下创制/可用图像)。使用nightly图像并不是latest图像,是因为latest包涵的二个bug会破坏TensorBoard,那是大家稍后要求的二个数码可视化学工业具。

# Unpersists graph from file

graph_def.ParseFromString

-v /path/to/local:/notebooks/local将刚创建的local目录挂载到容器中适当的量的任务。如果使用智跑HEL、Fedora或别的辅助SELinux的种类,增多:Z允许容器访问目录。

{'DecodeJpeg/contents:0': image_data})

办事规律

tf_logging.py, line 82.

分拣脚本中的图表加载代码已经被毁损,在此间,作者用graph_def = tf.GraphDef()等作为图表加载代码。

image_path = sys.argv[1]

可望你能够三番两次关切本博客的成千上万博文。

top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]

echo 'db6b71d5d3afff90302ee17fd1fefc11d57f243f flower_photos.tgz' | sha1sum -c

image_data = tf.gfile.FastGFile(image_path, 'rb').read()

在输出上,大家意在有较高的“演练精度”和“验证精度”,以及十分低的“交叉熵”。有关那些术语的详实分解,请参见“怎样就新图片类型再陶冶英斯ption的末尾一层”。在近年来的硬件上的锻练约30分钟。

# Loads label file, strips off carriage return

predictions = sess.run(softmax_tensor,

dandelion (score = 0.00605)

labels_path = 'output_labels.txt'

# Read in the image_data

sunflowers (score = 0.78311)

/bin/bash钦点运转Bash shell,而不运维连串默许命令。

echo 'a74361beb4f763dc2d0101cfe87b672ceae6e2f5 retrain.py' | sha1sum -c

--output_labels output_labels.txt

小说原标题《Learn how to classify images with TensorFlow》,译者:Mags,审校:袁虎。

--name tensorflow将容器命名字为tensorflow,并非sneaky_chowderhead或别的Docker定义的随便名字。

# Sort to show labels of first prediction in order of confidence

cd local

•标明:管理操练多少。比方花卉,将雏菊的图像放到“雏菊”目录下,将玫瑰放到“玫瑰”目录下等等,将尽心多的两样门类的繁花依照项目不一样放在不相同的目录下。假诺大家不标明“蕨类植物”,那么分类器永恒也不会重回“蕨类植物”。那亟需各种项指标洋洋样书,由此这一步很要紧,何况很耗费时间。(本文使用预先标志好的数码以升高效用)

_ = tf.import_graph_def(graph_def, name='')

明确retrain.py有准确的内容,你应当看到retrain.py: OK.。

with tf.gfile.FastGFile(graph_path, 'rb') as f:

在无数TensorFlow教程中最初且独一信赖的正是Docker(应该申明那是个合理的上马)。我也更爱好这种装置TensorFlow的主意,因为无需安装一密密麻麻的重视项,那足以保障主机相比较根本。

将下述脚本命名字为 classify.py保存在地面local目录:

安装Docker后,我们计划运转八个练习和归类的TensorFlow容器。在硬盘上创设一个2GB空闲空中的做事目录,创设三个名叫local的子目录,并记下完整路径。

如上为译文。

请留神调节台出口的终极一行:

curl -O

docker run -v /path/to/local:/notebooks/local --rm -it --name tensorflow

human_string = label_lines[node_id]

INFO:tensorflow:Final test accuracy = 89.1%

假设遇上如下错误,忽略它:

再增添叁个小本子,就能够将新的繁花图像加多到模型中,并出口测量试验结果。那正是图像分类。

print('%s (score = %.5f)' % (human_string, score))

假定没有看出“flower_photos.tgz”新闻:表达文件不精确。假设上诉curl 或sha1sum手续战败,请手动下载磨练多少包并解压(SHA-1 校验码:db6b71d5d3afff90302ee17fd1fefc11d57f243f)到地面主机的local目录下。

roses (score = 0.00073)

本种类文章直接切加入关贸总协定协会键的片段,只须要对命令行和Python有最核心的摸底,就足以在家神速地开创一些让你激动不已的品类。本文不会深深斟酌TensorFlow的办事原理,要是你想理解越来越多,作者会提供大批量附加的参照他事他说加以考察资料。本类别具有的库和工具都以无偿开源的软件。

-it 连接输入输出,达成互动。

运用零基础知识和一部分代码,大家建了一个相当好的花卉图像分类器,在现存的台式机计算机上每秒大约能够管理5张图像。

with tf.Session() as sess:

6d2793cb67207a085d0/tensorflow/examples/image_retraining/retrain.py

Bootstrap TensorFlow

graph_def = tf.GraphDef()

咱俩再一次陶冶的模型是英斯ption v3,最早是在二零一五年十一月发表的诗歌“重新挂念Computer视觉的英斯ption架构”中有做论述。

import tensorflow as tf, sys

python retrain.py --image_dir flower_photos --output_graph output_graph.pb

TypeError: not all arguments converted during string formatting Logged from file

在那一个由两有个别构成的多级中,笔者将呈报如何火速的开创二个利用于图像识其余卷积神经网络。TensorFlow总计步骤是互相的,可对其布局实行逐帧录制剖判,也可对其扩大实行时间感知录像深入分析。

in tf.gfile.GFile(labels_path)]

纵深学习算法与Computer硬件质量的升高,使探讨职员和商社在图像识别、语音识别、推荐引擎和机械翻译等世界获得了伟大的前进。三年前,视觉方式识别领域得到了第二个超脱凡俗的战果。三年前,谷歌(Google)大脑团队支付了TensorFlow,并将深度学习美妙的利用于各类领域。现在,TensorFlow则超过了成都百货上千用来深度学习的目眩神摇工具。

数量注脚了整套!模型鲜明图像中的花朵是向阳花的正确度为78.311%。数值越高证明相配度越高。请稳重,只好有三个格外类型。多标签分类则必要其它二个例外的法门。

•磨练:将标记好的数目提需求模型。有一个工具将轻松抓取一群图像,使用模型推断种种花的品种,测量检验预计的正确性,重复实行,直到使用了许多陶冶多少截至。最终一群未被利用的图像用于计算该练习模型的正确性。

未来把演习多少放好,然后对再演习脚本举办下载和完整性检查。

本学科将磨炼四个用于识别差异品类花朵的图像分类器。深度学习须求多量的教练多少,由此,我们供给大批量已分类的繁花图像。值得庆幸的是,另外多少个模子在图像收集和分类这上头做得不行奇妙,所以我们利用这么些带有脚本的已分类数据集,它有现存且完全磨练过的图像分类模型,重新兵演练练模型的结尾几层以达到大家想要的结果,这种技能称为迁移学习。

结束大家做了这几个约20秒钟的演习,英斯ption才知晓什么鉴定分别雏菊和紫述香,那就是深浅学习中的“学习”部分。

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 教程 tensorflow 图像 深度学习 入门