1. Başlamadan önce
Bu codelab'de, REST ve gRPC ile TensorFlow Serving kullanarak bir web sitesinden görüntü sınıflandırma çıkarımı çalıştırmayı öğreneceksiniz.
Ön koşullar
- HTML ve JavaScript gibi web geliştirme konusunda temel bilgiler
- Eğitim ve dağıtım gibi TensorFlow ile makine öğrenimi hakkında temel bilgiler
- Terminaller ve Docker hakkında temel bilgiler
Neler öğreneceksiniz?
- TensorFlow Hub'da önceden eğitilmiş görüntü sınıflandırma modellerini bulma
- TensorFlow Serving (REST ve gRPC) aracılığıyla indirilen görüntü sınıflandırma modeliyle basit bir web sitesi oluşturma ve tahmin yapma
- Algılama sonucunu kullanıcı arayüzünde nasıl oluşturacağınız.
İhtiyacınız olanlar
- Docker
- Google Chrome
- Web Server for Chrome
- Node.js ve NPM
- Bash
- Protokol arabelleği derleyicisi (yalnızca gRPC saplamasını kendiniz yeniden oluşturmak istiyorsanız gereklidir)
- gRPC-web kodu oluşturma eklentisi (yalnızca gRPC sapını kendiniz yeniden oluşturmak istiyorsanız gereklidir)
2. Hazırlanın
Bu codelab'in kodunu indirmek için:
- Bu GitHub deposuna gidin.
- Bu codelab'in tüm kodunu indirmek için Code > Download zip'i (Kod > Zip dosyasını indir) tıklayın.
- İndirilen ZIP dosyasını açarak ihtiyacınız olan tüm kaynakların bulunduğu bir
codelabs
kök klasörünü çıkarın.
Bu codelab için depodaki TFServing/ImageClassificationWeb
alt dizinindeki dosyalar yeterlidir. Bu dizinde iki klasör bulunur:
starter
klasörü, bu codelab'de temel alacağınız başlangıç kodunu içerir.finished
klasöründe, tamamlanmış örnek uygulamanın kodu yer alır.
3. Bağımlılıkları yükleyin
Bağımlılıkları yüklemek için:
- Terminalinizde
starter
klasörüne gidin ve gerekli NPM paketlerini yükleyin:
npm install
4. Başlangıç web sitesini çalıştırma
TFServing/ImageClassificationWeb/starter/dist/index.html
dosyasını yüklemek için Web Server for Chrome'u kullanın:
- Chrome'un adres çubuğuna
Chrome://apps/
yazın ve uygulama listesinde Web Server for Chrome'u bulun. - Web Server for Chrome'u başlatın ve
TFServing/ImageClassificationWeb/starter/dist/
klasörünü seçin. - Etkinleştirmek için Web Sunucusu açma/kapatma düğmesini tıklayın ve tarayıcınızda http://localhost:8887/ adresine gidin.
Web sitesini çalıştırma ve keşfetme
Web sitesini artık görmeniz gerekir. Kullanıcı arayüzü oldukça basittir: Sınıflandırmak istediğiniz bir kedi resmi vardır ve kullanıcı, verileri REST veya gRPC ile arka uca gönderebilir. Arka uç, görüntü üzerinde görüntü sınıflandırması gerçekleştirir ve sınıflandırma sonucunu, sonucu görüntüleyen web sitesine döndürür.
Sınıflandır'ı tıkladığınızda henüz arka uçla iletişim kurulamadığından hiçbir şey olmaz.
5. TensorFlow Serving ile görüntü sınıflandırma modeli dağıtma
Görüntü sınıflandırma, bir görüntüyü, görüntünün birincil içeriğine göre önceden tanımlanmış kategorilere sınıflandıran çok yaygın bir makine öğrenimi görevidir. Çiçekleri sınıflandırma örneğini aşağıda görebilirsiniz:
TensorFlow Hub'da önceden eğitilmiş çeşitli görüntü sınıflandırma modelleri bulunur. Bu codelab'de popüler bir Inception v3 modeli kullanacaksınız.
TensorFlow Serving ile görüntü sınıflandırma modelini dağıtmak için:
- Inception v3 model dosyasını indirin.
- İndirilen
.tar.gz
dosyasını 7-Zip gibi bir sıkıştırma açma aracıyla açın. inception_v3
klasörü oluşturun ve ardından bu klasörün içinde bir123
alt klasörü oluşturun.- Ayıklanan
variables
klasörünü vesaved_model.pb
dosyasını123
alt klasörüne yerleştirin.
inception_v3
klasörünü SavedModel
klasörü olarak adlandırabilirsiniz. 123
, örnek bir sürüm numarasıdır. İsterseniz başka bir numara seçebilirsiniz.
Klasör yapısı aşağıdaki resimdeki gibi olmalıdır:
TensorFlow Serving'i başlatma
- Terminalinizde, Docker ile TensorFlow Serving'i başlatın ancak
PATH/TO/SAVEDMODEL
yerine bilgisayarınızdakiinception_v3
klasörünün mutlak yolunu kullanın.
docker pull tensorflow/serving docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/inception" -e MODEL_NAME=inception tensorflow/serving
Docker, önce TensorFlow Serving görüntüsünü otomatik olarak indirir. Bu işlem bir dakika sürer. Ardından TensorFlow Serving başlatılmalıdır. Günlük, aşağıdaki kod snippet'i gibi görünmelidir:
2022-02-25 06:01:12.513231: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle. 2022-02-25 06:01:12.585012: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 3000000000 Hz 2022-02-25 06:01:13.395083: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/inception/123 2022-02-25 06:01:13.837562: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 1928700 microseconds. 2022-02-25 06:01:13.877848: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/inception/123/assets.extra/tf_serving_warmup_requests 2022-02-25 06:01:13.929844: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: inception version: 123} 2022-02-25 06:01:13.985848: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models 2022-02-25 06:01:13.985987: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled 2022-02-25 06:01:13.988994: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ... [warn] getaddrinfo: address family for nodename not supported 2022-02-25 06:01:14.033872: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ... [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
6. Envoy proxy'yi ayarlama
TensorFlow Serving şu anda Access-Control-Allow-Origin
üstbilgisini ayarlamadığı için tarayıcı, güvenlik nedeniyle ön uç JavaScript'inden TensorFlow Serving'e yapılan isteği engelliyor. Bu sorunu çözmek için JavaScript'ten TensorFlow Serving arka ucuna yapılan isteği proxy'lemek üzere Envoy gibi bir proxy kullanmanız gerekir.
Envoy'u başlatma
- Terminalinizde Envoy görüntüsünü indirin ve Docker ile Envoy'u başlatın. Ancak
PATH/TO/ENVOY-CUSTOM.YAML
yer tutucusunustarter
klasöründekienvoy-custom.yaml
dosyasının mutlak yoluyla değiştirin.
docker pull envoyproxy/envoy-dev:fd3e8370ddb7a96634c192d1461516e6de1d1797 docker run --add-host host.docker.internal:host-gateway --rm -it -p 9901:9901 -p 8000:8000 -p 8080:8080 -v PATH/TO/ENVOY-CUSTOM.YAML:/envoy-custom.yaml envoyproxy/envoy-dev:fd3e8370ddb7a96634c192d1461516e6de1d1797 -c /envoy-custom.yaml
Docker, önce Envoy görüntüsünü otomatik olarak indirir. Ardından Envoy başlatılmalıdır. Günlük, aşağıdaki kod snippet'i gibi görünmelidir:
[2022-03-02 07:51:48.563][1][info][main] [source/server/server.cc:436] response trailer map: 152 bytes: grpc-message,grpc-status [2022-03-02 07:51:48.681][1][info][main] [source/server/server.cc:772] runtime: {} [2022-03-02 07:51:48.682][1][info][admin] [source/server/admin/admin.cc:134] admin address: 0.0.0.0:9901 [2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:127] loading tracing configuration [2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:87] loading 0 static secret(s) [2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:93] loading 2 cluster(s) [2022-03-02 07:51:48.687][1][info][config] [source/server/configuration_impl.cc:97] loading 2 listener(s) [2022-03-02 07:51:48.694][1][info][config] [source/server/configuration_impl.cc:109] loading stats configuration [2022-03-02 07:51:48.696][1][info][main] [source/server/server.cc:868] starting main dispatch loop [2022-03-02 07:51:48.881][1][info][runtime] [source/common/runtime/runtime_impl.cc:446] RTDS has finished initialization [2022-03-02 07:51:48.881][1][info][upstream] [source/common/upstream/cluster_manager_impl.cc:207] cm init: all clusters initialized [2022-03-02 07:51:48.881][1][info][main] [source/server/server.cc:849] all clusters initialized. initializing init manager [2022-03-02 07:51:48.881][1][info][config] [source/server/listener_manager_impl.cc:784] all dependencies initialized. starting workers [2022-03-02 07:51:48.902][1][warning][main] [source/server/server.cc:747] there is no configured limit to the number of allowed active connections. Set a limit via the runtime key overload.global_downstream_max_connections
7. REST aracılığıyla web sitesini TensorFlow'a bağlama
Arka uç artık hazır olduğundan, görüntüleri sınıflandırmak için TensorFlow Serving'e istemci istekleri gönderebilirsiniz. TensorFlow Serving'e istek göndermenin iki yolu vardır:
- REST
- gRPC
REST üzerinden istek gönderme ve yanıt alma
REST üzerinden istek göndermek ve almak için üç basit adım vardır:
- REST isteğini oluşturun.
- REST isteğini TensorFlow Serving'e gönderin.
- Tahmin edilen sonucu REST yanıtından çıkarın ve sonucu gösterin.
Bu adımları src/index.js
dosyasında gerçekleştirirsiniz.
REST isteğini oluşturma
Şu anda classify_img()
işlevi, REST isteğini TensorFlow Serving'e göndermiyor. Öncelikle bir REST isteği oluşturmak için bu REST dalını uygulamanız gerekir:
if (radioButtons[0].checked) {
console.log('Using REST');
// TODO: Add code to send a REST request to TensorFlow Serving.
}
TensorFlow Serving, kullandığınız Inception v3 modeli için görüntü tensörünü içeren bir POST isteği bekler. Bu nedenle, görüntünün her pikselinden RGB değerlerini bir diziye çıkarmanız ve ardından diziyi isteğin yükü olan bir JSON'a sarmalamanız gerekir.
- Bu kodu REST dalına ekleyin:
//Create the REST request.
let imgTensor = new Array();
let pixelArray = new Array();
context.drawImage(img, 0, 0);
for(let i=0; i<inputImgHeight; i++) {
pixelArray[i] = new Array();
for (let j=0; j<inputImgWidth; j++) {
pixelArray[i][j] = new Array();
pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[0]/255);
pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[1]/255);
pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[2]/255);
}
}
imgTensor.push(pixelArray);
const RESTURL = 'http://localhost:8000/v1/models/inception:predict';
let xhr = new XMLHttpRequest();
xhr.open('POST', RESTURL);
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8;');
let data = JSON.stringify({
instances: imgTensor
});
xhr.onload = () => {
}
xhr.onerror = () => {
console.log('REST request error');
}
REST isteğini TensorFlow Serving'e gönderme
Artık isteği gönderebilirsiniz.
- Bu kodu, REST dalında yukarıdaki kodun hemen sonrasına ekleyin:
// Send the REST request.
xhr.send(data);
TensorFlow Serving'den gelen REST yanıtını işleme
Inception v3 modeli, resmin önceden tanımlanmış kategorilere ait olma olasılıklarının bir dizisini döndürür. Tahmin başarılı olduğunda, kullanıcı arayüzünde en olası kategoriyi göstermeniz gerekir.
Yanıtı işlemek için onload()
işleyicisini uygularsınız.
xhr.onload = () => {
}
- Bu kodu
onload()
dinleyicisine ekleyin:
// Process the REST response.
const response = JSON.parse(xhr.responseText);
const maxIndex = argmax(response['predictions'][0])
document.getElementById('category').textContent = 'Predicted category: ' + maxIndex;
Dinleyici artık yanıttan tahmin edilen olasılıkları çıkarıyor, nesnenin en olası kategorisini tanımlıyor ve sonucu kullanıcı arayüzünde gösteriyor.
Çalıştırın
- Terminalinizde
starter
klasörüne gidin ve webpack'i kullanarak tüm JavaScript dosyalarınıdist/index.html
dosyasına yerleştirebileceğiniz tek bir dosyada paketleyin:
npm install -g npx npm install --save-dev webpack npx webpack
- Tarayıcınızda http://localhost:8887/ adresini yenileyin ve REST > Classify'ı (REST > Sınıflandır) tıklayın.
Web sitesi, ImageNet veri kümesindeki Egyptian Cat
etiketine karşılık gelen 286
kategorisini tahmin edilen kategori olarak gösteriyor.
8. Web sitesini gRPC aracılığıyla TensorFlow Serving'e bağlama
TensorFlow Serving, REST'in yanı sıra gRPC'yi de destekler.
gRPC, herhangi bir ortamda çalışabilen modern, açık kaynaklı ve yüksek performanslı bir Uzak Prosedür Çağrısı (RPC) çerçevesidir. Yük dengeleme, izleme, sağlık kontrolü ve kimlik doğrulama için takılabilir destekle veri merkezlerindeki ve veri merkezleri arasındaki hizmetleri verimli bir şekilde bağlayabilir. gRPC'nin pratikte REST'ten daha iyi performans gösterdiği gözlemlenmiştir.
gRPC ile istek gönderme ve yanıt alma
Dört basit adım vardır:
- İsteğe bağlı: gRPC istemci taslağı kodunu oluşturun.
- gRPC isteğini oluşturun.
- gRPC isteğini TensorFlow Serving'e gönderin.
- Tahmin edilen sonucu gRPC yanıtından çıkarın ve kullanıcı arayüzünde gösterin.
Bu adımları src/index.js
dosyasında tamamlarsınız.
İsteğe bağlı: gRPC istemci taslağı kodunu oluşturma
TensorFlow Serving ile gRPC'yi kullanmak için gRPC iş akışını uygulamanız gerekir. Ayrıntılar hakkında daha fazla bilgi edinmek için gRPC belgelerine bakın.
TensorFlow Serving ve TensorFlow, .proto
dosyalarını sizin için tanımlar. TensorFlow ve TensorFlow Serving 2.8'den itibaren şu .proto
dosyaları gereklidir:
tensorflow/core/example/example.proto
tensorflow/core/example/feature.proto
tensorflow/core/protobuf/struct.proto
tensorflow/core/protobuf/saved_object_graph.proto
tensorflow/core/protobuf/saver.proto
tensorflow/core/protobuf/trackable_object_graph.proto
tensorflow/core/protobuf/meta_graph.proto
tensorflow/core/framework/node_def.proto
tensorflow/core/framework/attr_value.proto
tensorflow/core/framework/function.proto
tensorflow/core/framework/types.proto
tensorflow/core/framework/tensor_shape.proto
tensorflow/core/framework/full_type.proto
tensorflow/core/framework/versions.proto
tensorflow/core/framework/op_def.proto
tensorflow/core/framework/graph.proto
tensorflow/core/framework/tensor.proto
tensorflow/core/framework/resource_handle.proto
tensorflow/core/framework/variable.proto
tensorflow_serving/apis/inference.proto
tensorflow_serving/apis/classification.proto
tensorflow_serving/apis/predict.proto
tensorflow_serving/apis/regression.proto
tensorflow_serving/apis/get_model_metadata.proto
tensorflow_serving/apis/input.proto
tensorflow_serving/apis/prediction_service.proto
tensorflow_serving/apis/model.proto
- Terminalinizde
starter/src/proto/
klasörüne gidin ve sap oluşturun:
bash generate_grpc_stub_js.sh
gRPC isteğini oluşturma
REST isteğine benzer şekilde, gRPC isteğini gRPC dalında oluşturursunuz..
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
}
else {
print("Using gRPC")
// TODO: Add code to send a gRPC request to TensorFlow Serving.
}
- Bu kodu gRPC dalına ekleyin:
// Create the gRPC request.
const PredictModule = require('./proto/generated/tensorflow_serving/apis/predict_pb.js');
const PredictionServiceClientModule = require('./proto/generated/tensorflow_serving/apis/prediction_service_grpc_web_pb.js');
const ModelModule = require('./proto/generated/tensorflow_serving/apis/model_pb.js');
const TensorModule = require('./proto/generated/tensorflow/core/framework/tensor_pb.js');
const GPRCURL = 'http://localhost:8080';
const stub = new PredictionServiceClientModule.PredictionServiceClient(GPRCURL);
const modelSpec = new ModelModule.ModelSpec();
modelSpec.setName('inception');
const tensorProto = new TensorModule.TensorProto();
const tensorShapeProto = new TensorModule.TensorShapeProto();
const batchDim = (new TensorModule.TensorShapeProto.Dim()).setSize(1);
const heightDim = (new TensorModule.TensorShapeProto.Dim()).setSize(inputImgHeight);
const widthDim = (new TensorModule.TensorShapeProto.Dim()).setSize(inputImgWidth);
const channelDim = (new TensorModule.TensorShapeProto.Dim()).setSize(3);
tensorShapeProto.setDimList([batchDim, heightDim, widthDim, channelDim]);
tensorProto.setDtype(proto.tensorflow.DataType.DT_FLOAT);
tensorProto.setTensorShape(tensorShapeProto);
context.drawImage(img, 0, 0);
for(let i=0; i<inputImgHeight; i++) {
for (let j=0; j<inputImgWidth; j++) {
tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[0]/255);
tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[1]/255);
tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[2]/255);
}
}
const predictionServiceRequest = new PredictModule.PredictRequest();
predictionServiceRequest.setModelSpec(modelSpec);
predictionServiceRequest.getInputsMap().set('inputs', tensorProto);
gRPC isteğini TensorFlow Serving'e gönderme
Artık isteği gönderebilirsiniz.
- Bu kodu, önceki kod snippet'indeki gRPC dalındaki kodun hemen sonrasına ekleyin:
// Send the gRPC request.
stub.predict(predictionServiceRequest, {}, function(err, response) {
// TODO: Add code to process the response.
});
TensorFlow Serving'den gelen gRPC yanıtını işleme
Son olarak, yanıtı işlemek için yukarıdaki geri çağırma işlevini uygularsınız.
- Bu kodu, önceki kod snippet'indeki işlev gövdesine ekleyin:
// Process the gRPC response.
if (err) {
console.log(err.code);
console.log(err.message);
}
else {
const maxIndex = argmax(response.getOutputsMap().get('logits').getFloatValList());
document.getElementById('category').textContent = 'Predicted category: ' + maxIndex;
}
Dinleyici artık yanıttan tahmin edilen olasılıkları çıkarıyor, nesnenin en olası kategorisini tanımlıyor ve sonucu kullanıcı arayüzünde gösteriyor.
Çalıştırın
- Terminalinizde, tüm JavaScript dosyalarını
index.html
dosyasına yerleştirebileceğiniz tek bir dosyada paketlemek için webpack'i kullanın:
npx webpack
- Tarayıcınızda http://localhost:8887/ adresini yenileyin.
- gRPC > Classify'ı (Sınıflandır) tıklayın.
Web sitesinde, ImageNet veri kümesindeki Egyptian Cat
etiketine karşılık gelen 286
tahmini kategorisi gösteriliyor.
9. Tebrikler
Web sitenize görüntü sınıflandırma özellikleri eklemek için TensorFlow Serving'i kullandınız.