1. Başlamadan önce
Bu codelab'de, REST ve gRPC ile TensorFlow Sunumu'nu kullanarak web sitesinden görüntü sınıflandırma çıkarımının nasıl çalıştırılacağını öğreneceksiniz.
Ön koşullar
- HTML ve JavaScript gibi temel web geliştirme bilgileri
- TensorFlow'da eğitim ve dağıtım gibi temel makine öğrenimi bilgileri
- Terminaller ve Docker hakkında temel bilgiler
Neler öğreneceksiniz?
- TensorFlow Hub'da önceden eğitilmiş görüntü sınıflandırma modelleri bulma.
- TensorFlow Sunumu (REST ve gRPC) ile indirilen görüntü sınıflandırma modeliyle basit bir web sitesi oluşturma ve tahminde bulunma.
- Kullanıcı arayüzünde algılama sonucu nasıl oluşturulur?
Gerekenler
- Docker
- Google Chrome
- Chrome için Web Sunucusu
- Node.js ve NPM
- Karma
- Protokol arabelleği derleyicisi (yalnızca gRPC stub'unu kendiniz yeniden oluşturmak isterseniz gereklidir)
- gRPC-web code generator eklentisi (yalnızca gRPC stub'u kendiniz yeniden oluşturmak istiyorsanız gereklidir)
2. Hazırlanın
Bu codelab'in kodunu indirmek için:
- Bu GitHub veri havuzuna gidin.
- Bu codelab'e ait tüm kodu indirmek için Code > İndir ZIP'i tıklayın.
- İhtiyaç duyduğunuz tüm kaynaklarla bir
codelabs
kök klasörünün paketini açmak için indirilen zip dosyasını açın.
Bu codelab için yalnızca depodaki TFServing/ImageClassificationWeb
alt dizininde bulunan ve iki klasör içeren dosyalara ihtiyacınız vardır:
starter
klasörü, bu codelab için geliştirmekte olduğunuz başlangıç kodunu içerir.finished
klasörü, tamamlanan örnek uygulama için tamamlanmış kodu içerir.
3. Bağımlılıkları yükleyin
Bağımlıları yüklemek için:
- Terminalinizde
starter
klasörüne gidip gerekli NPM paketlerini yükleyin:
npm install
4. Başlangıç web sitesini çalıştır
TFServing/ImageClassificationWeb/starter/dist/index.html
dosyasını yüklemek için Chrome için Web Sunucusu'nu kullanın:
- Chrome'un adres çubuğuna
Chrome://apps/
ifadesini girin ve uygulama listesinde Chrome için Web Sunucusu'nu bulun. - Chrome için Web Sunucusu'nu başlatın, ardından
TFServing/ImageClassificationWeb/starter/dist/
klasörünü seçin. - Etkinleştirmek için Web Sunucusu açma/kapatma düğmesini tıklayarak tarayıcınızda http://localhost:8887/ adresine gidin.
Web sitesini çalıştırıp keşfedin
Web sitesini hemen 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 ucuna gönderebilir. Arka uç, resimde resim sınıflandırması yapar ve sınıflandırma sonucunu web sitesine döndürür.
Sınıflandır'ı tıklarsanız arka uçla henüz iletişim kuramadığı için hiçbir şey olmaz.
5. TensorFlow Sunumu ile görüntü sınıflandırma modeli dağıtma
Görüntü sınıflandırma, resmi birincil içeriğe göre önceden tanımlanmış kategoriler halinde sınıflandıran çok yaygın bir makine öğrenimi görevidir. Çiçekleri sınıflandırmaya dair bir örneği burada bulabilirsiniz:
TensorFlow Hub'da önceden eğitilmiş bir dizi görüntü sınıflandırma modeli bulunur. Bu codelab için popüler bir Inception v3 modeli kullanıyorsunuz.
TensorFlow Sunumu ile görüntü sınıflandırma modelini dağıtmak için:
- Inception v3 model dosyasını indirin.
- İndirilen
.tar.gz
dosyasının sıkıştırmasını açmak için 7-Zip gibi bir sıkıştırma aracı kullanın. inception_v3
klasörü ve ardından123
alt klasörü oluşturun.- Çıkarılan
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 gibi görünmelidir:
TensorFlow Sunumunu Başlat
- Terminalinizde TensorFlow Sunumu'nu Docker ile başlatın ancak
PATH/TO/SAVEDMODEL
öğesini bilgisayarınızdakiinception_v3
klasörünün mutlak yoluyla değiştirin.
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 bir dakika sürecek TensorFlow Sunumu resmini otomatik olarak indirir. Ardından, TensorFlow Sunumu başlatılmalıdır. Günlük, şu kod snippet'i gibi olmalıdır:
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
Şu anda TensorFlow Sunumu Access-Control-Allow-Origin
üst bilgisini ayarlamadığından tarayıcı, güvenlik nedeniyle ön uç JavaScript'ten TensorFlow Sunumu'na gönderilen isteği engeller. Bu sorunu çözmek için JavaScript'ten TensorFlow Sunum arka ucuna proxy uygulamak amacıyla Envoy gibi bir proxy kullanmanız gerekir.
Envoy'u başlat
- Terminalinizde Envoy görüntüsünü indirip Envoy'u Docker ile 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 resmini otomatik olarak indirir. Sonrasında Envoy başlamalıdır. Günlük, şu kod snippet'i gibi olmalıdır:
[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 üzerinden web sitesini TensorFlow ile bağlama
Arka uç hazır. Böylece, resimleri sınıflandırmak için TensorFlow Sunumu'na istemci istekleri gönderebilirsiniz. TensorFlow Sunumu'na istek göndermenin iki yolu vardır:
- REST
- gRPC
İstek ve REST aracılığıyla yanıt alma
REST üzerinden istek gönderip almak için üç basit adım vardır:
- REST isteğini oluşturun.
- REST isteğini TensorFlow Sunumu'na gönderin.
- Tahmin edilen sonucu REST yanıtından çıkarıp sonucu görüntüleyin.
Bu adımları src/index.js
dosyasında bulabilirsiniz.
REST isteğini oluşturun
Şu anda classify_img()
işlevi, REST isteğini TensorFlow Sunumu'na göndermez. Öncelikle 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 Sunumu, kullandığınız Inception v3 modeli için görüntü tensörünü içeren bir POST isteği bekler. Bu nedenle, resmin her pikselinden RGB değerlerini bir diziye çıkarmanız ve ardından diziyi, isteğin yükü olan bir JSON içinde sarmalamanız gerekir.
- Bu kodu REST şubesine 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 Sunumu'na gönder
Artık isteği gönderebilirsiniz.
- Bu kodu REST şubesindeki yukarıdaki kodun hemen sonrasında ekleyin:
// Send the REST request.
xhr.send(data);
TensorFlow Delivery'den REST yanıtını işleme
Inception v3 modeli, resmin önceden tanımlanmış kategorilere ait bir dizi olasılık döndürür. Tahmin başarılı olduğunda, kullanıcı arayüzündeki en olası kategori kategorisini çıkarmanız gerekir.
Yanıtı işlemek için onload()
işleyiciyi uygularsınız.
xhr.onload = () => {
}
- Bu kodu
onload()
işleyicisine ekleyin:
// Process the REST response.
const response = JSON.parse(xhr.responseText);
const maxIndex = argmax(response['predictions'][0])
document.getElementById('category').textContent = 'Predicted category: ' + maxIndex;
Şimdi dinleyici, olası olasılıkları yanıttan çıkarıp nesnenin en olası kategorisini belirler ve sonucu kullanıcı arayüzünde gösterir.
Çalıştır
- Terminalinizde
starter
klasörüne gidin ve tüm JavaScript dosyalarınıdist/index.html
dosyasına yerleştirebileceğiniz tek bir dosya halinde paketlemek için web paketi kullanın:
npm install -g npx npm install --save-dev webpack npx webpack
- Tarayıcınızda http://localhost:8887/ adresini yenileyin ve ardından REST > Classify'ı tıklayın.
Web sitesi, tahmin edilen kategori olarak 286
'i gösterir. Bu kategori, ImageNet veri kümesindeki Egyptian Cat
etiketiyle eşlenir.
8. Web sitesini gRPC aracılığıyla TensorFlow Sunumu ile bağlama
TensorFlow Sunumu, REST'e ek olarak gRPC'yi de destekler.
gRPC, tüm ortamlarda çalışabilen modern, açık kaynaklı, yüksek performanslı bir Uzaktan Prosedür Çağrısı (RPC) çerçevesidir. Yük dengeleme, izleme, sağlık kontrolü ve kimlik doğrulama konularında takılabilir destek sayesinde veri merkezlerinde ve veri merkezlerinde hizmetleri etkili şekilde bağlayabilir. gRPC'nin uygulamada REST'ten daha iyi performans gösterdiği gözlemlenmiştir.
gRPC ile istek gönderme ve yanıtlar alma
Dört basit adım vardır:
- İsteğe bağlı: gRPC istemci stub kodunu oluşturun.
- gRPC isteğini oluşturun.
- gRPC isteğini TensorFlow Sunumu'na gönderin.
- Tahmin edilen sonucu gRPC yanıtından çıkarın ve kullanıcı arayüzünde görüntüleyin.
Bu adımları src/index.js
dosyasında tamamlarsınız.
İsteğe bağlı: gRPC istemci stub kodunu oluşturun
gRPC'yi TensorFlow Sunumu ile kullanmak için gRPC iş akışını uygulamanız gerekir. Ayrıntılar hakkında bilgi edinmek için gRPC dokümanlarına bakın.
TensorFlow Sunumu ve TensorFlow, .proto
dosyalarını sizin için tanımlar. TensorFlow ve TensorFlow Sunumu 2.8 itibarıyla şu dosyalar gerekli .proto
:
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 saplama oluşturun:
bash generate_grpc_stub_js.sh
gRPC isteğini oluşturma
REST isteğine benzer şekilde gRPC isteğinde gRPC isteğini 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 Sunumu'na gönderme
Artık isteği gönderebilirsiniz.
- Bu kodu, önceki kod snippet'indeki gRPC şubesindeki koddan hemen sonra ekleyin:
// Send the gRPC request.
stub.predict(predictionServiceRequest, {}, function(err, response) {
// TODO: Add code to process the response.
});
TensorFlow Sunumundan 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;
}
Şimdi dinleyici, olası olasılıkları yanıttan çıkarıp nesnenin en olası kategorisini belirler ve sonucu kullanıcı arayüzünde gösterir.
Çalıştır
- Terminalinizde, tüm JavaScript dosyalarını
index.html
dosyasına yerleştirebileceğiniz tek bir dosyada paketlemek için web paketini kullanın:
npx webpack
- Tarayıcınızda http://localhost:8887/ sayfasını yenileyin.
- gRPC > Classify'ı tıklayın.
Web sitesi, tahmini 286
kategorisini gösterir. Bu kategori, ImageNet veri kümesindeki Egyptian Cat
etiketiyle eşlenir.
9. Tebrikler
Web sitenize resim sınıflandırma özellikleri eklemek için TensorFlow Sunumunu kullandınız.