Resimleri sınıflandıran basit bir web sitesi oluşturun

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

2. Hazırlanın

Bu codelab'in kodunu indirmek için:

  1. Bu GitHub veri havuzuna gidin.
  2. Bu codelab'e ait tüm kodu indirmek için Code > İndir ZIP'i tıklayın.

a72f2bb4caa9a96.png

  1. İ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:

  1. Chrome'un adres çubuğuna Chrome://apps/ ifadesini girin ve uygulama listesinde Chrome için Web Sunucusu'nu bulun.
  2. Chrome için Web Sunucusu'nu başlatın, ardından TFServing/ImageClassificationWeb/starter/dist/ klasörünü seçin.
  3. Etkinleştirmek için Web Sunucusu açma/kapatma düğmesini tıklayarak tarayıcınızda http://localhost:8887/ adresine gidin.

f7b43cd44ebf1f1b.png

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.

837d97a27c59a0b3.png

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:

a6da16b4a7665db0.png

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:

  1. Inception v3 model dosyasını indirin.
  2. İ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.
  3. inception_v3 klasörü ve ardından 123 alt klasörü oluşturun.
  4. Çıkarılan variables klasörünü ve saved_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:

21a8675ac8d31907.png

TensorFlow Sunumunu Başlat

  • Terminalinizde TensorFlow Sunumu'nu Docker ile başlatın ancak PATH/TO/SAVEDMODEL öğesini bilgisayarınızdaki inception_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 tutucusunu starter klasöründeki envoy-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:

  1. REST isteğini oluşturun.
  2. REST isteğini TensorFlow Sunumu'na gönderin.
  3. 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

  1. 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
  1. 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.

c865a93b9b58335d.png

8. Web sitesini gRPC aracılığıyla TensorFlow Sunumu ile bağlama

TensorFlow Sunumu, REST'e ek olarak gRPC'yi de destekler.

b6f4449c2c850b0e.png

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:

  1. İsteğe bağlı: gRPC istemci stub kodunu oluşturun.
  2. gRPC isteğini oluşturun.
  3. gRPC isteğini TensorFlow Sunumu'na gönderin.
  4. 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.

a9d0e5cb543467b4.png

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

  1. 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
  1. Tarayıcınızda http://localhost:8887/ sayfasını yenileyin.
  2. 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.

Daha fazla bilgi