görsel sınıflandırma etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
görsel sınıflandırma etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

5 Aralık 2025 Cuma

WebGPU ile Tarayıcıda Makine Öğrenimi: ONNX Runtime Web ile Görsel Sınıflandırma (Adım Adım)

Giriş

WebGPU, modern tarayıcılarda GPU gücünden standart ve güvenli bir şekilde yararlanmayı sağlayan yeni bir web standardı. Bu yazıda, ONNX Runtime Web ve WebGPU kullanarak tarayıcı içinde tamamen istemci tarafında çalışan bir görsel sınıflandırma uygulamasını adım adım kuracağız. Sunucuya veri göndermeden, gizliliğe saygılı ve düşük gecikmeli bir makine öğrenimi deneyimi elde edeceğiz. Bu yaklaşım, SEO açısından da kıymetli; zira “tarayıcıda makine öğrenimi”, “WebGPU”, “ONNX Runtime Web”, “görsel sınıflandırma” gibi anahtar kelimelerle teknik kitlelere doğrudan hitap ediyor.

Ön Koşullar

- Güncel bir tarayıcı: Chrome 113+ sürümlerinde WebGPU masaüstünde varsayılan olarak açıktır. Safari’de ve Firefox’ta destek durumu değişebilir; deneysel bayraklar gerekebilir. Mobilde destek kısmi durumdadır.

- Node.js 18+ (geliştirme sunucusu ve paket yönetimi için)

- Temel HTML/JS bilgisi

Proje Kurulumu

1) Vite ile boş bir proje oluşturun:

npm create vite@latest webgpu-ml -- --template vanilla
cd webgpu-ml
npm install

2) ONNX Runtime Web paketini ekleyin:

npm i onnxruntime-web

3) Basit bir dosya yapısı hazırlayın: index.html, main.js ve bir models/ klasörü. Örnek olarak mobilenetv2.onnx gibi 224x224 giriş alan bir sınıflandırma modelini models/ altına yerleştirin. ONNX model arşivlerinden (örn. ResNet, MobileNet) hafif bir model tercih edin.

index.html İskeleti

Aşağıdaki minimal HTML, bir görsel yükleme alanı ve sonuçları göstermek için basit bir arayüz içerir.

<!doctype html>
<html lang="tr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>WebGPU ile Görsel Sınıflandırma</title>
  </head>
  <body>
    <h1>WebGPU + ONNX Runtime Web</h1>
    <input type="file" id="file" accept="image/*" />
    <button id="predict">Sınıflandır</button>
    <div id="status">Hazır</div>
    <div id="result"></div>
    <canvas id="canvas" width="224" height="224" style="display:none"></canvas>
    <script type="module" src="/main.js"></script>
  </body>
</html>

WebGPU ve ONNX Runtime Web ile Çalıştırma

Aşağıdaki kodda, tarayıcıda WebGPU desteği kontrol edilir, ONNX modeli yüklenir, görsel 224x224 boyutuna ölçeklenir ve ImageNet ortalama/standart sapma değerleri ile normalize edilerek tensöre dönüştürülür. Ardından model çıkarımı yapılır ve en yüksek olasılıklı sınıf ekrana yazdırılır.

// main.js
import * as ort from 'onnxruntime-web/webgpu';

const statusEl = document.getElementById('status');
const resultEl = document.getElementById('result');
const fileInput = document.getElementById('file');
const predictBtn = document.getElementById('predict');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let session;

// WebGPU desteğini kontrol edin
if (!('gpu' in navigator)) {
  statusEl.textContent = 'WebGPU desteklenmiyor. Varsayılan WASM ile deneyin.';
}

// Modeli başlat
async function initModel() {
  statusEl.textContent = 'Model yükleniyor...';
  // Fallback ile: önce WebGPU, olmazsa WASM
  session = await ort.InferenceSession.create('/models/mobilenetv2.onnx', {
    executionProviders: ['webgpu', 'wasm']
  });
  statusEl.textContent = 'Model yüklendi.';
}

function imageToTensor(img) {
  const size = 224;
  ctx.clearRect(0, 0, size, size);
  // Görseli 224x224'e çiz
  ctx.drawImage(img, 0, 0, size, size);
  const { data } = ctx.getImageData(0, 0, size, size);

  // NHWC(RGBA) -> NCHW, normalize [0,1], ImageNet mean/std
  const mean = [0.485, 0.456, 0.406];
  const std = [0.229, 0.224, 0.225];

  const input = new Float32Array(1 * 3 * size * size);
  let idx = 0;
  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      const i = (y * size + x) * 4;
      const r = data[i] / 255;
      const g = data[i + 1] / 255;
      const b = data[i + 2] / 255;
      // Kanal sırası: [R plane][G plane][B plane]
      input[0 * size * size + idx] = (r - mean[0]) / std[0];
      input[1 * size * size + idx] = (g - mean[1]) / std[1];
      input[2 * size * size + idx] = (b - mean[2]) / std[2];
      idx++;
    }
  }
  return new ort.Tensor('float32', input, [1, 3, size, size]);
}

function softmax(arr) {
  const max = Math.max(...arr);
  const exps = arr.map(v => Math.exp(v - max));
  const sum = exps.reduce((a, b) => a + b, 0);
  return exps.map(v => v / sum);
}

async function runInference(img) {
  if (!session) await initModel();

  statusEl.textContent = 'Çıkarım yapılıyor...';
  const tensor = imageToTensor(img);

  const inputName = session.inputNames[0];
  const output = await session.run({ [inputName]: tensor });

  const outputName = session.outputNames[0];
  const logits = Array.from(output[outputName].data);
  const probs = softmax(logits);

  // En yüksek olasılıklı sınıfı bul
  let bestIdx = 0;
  for (let i = 1; i < probs.length; i++) {
    if (probs[i] > probs[bestIdx]) bestIdx = i;
  }

  // Label dosyanız varsa fetch edip eşleyebilirsiniz (örn. imagenet-labels.txt)
  resultEl.textContent = `Tahmin sınıf index: ${bestIdx}, olasılık: ${(probs[bestIdx] * 100).toFixed(2)}%`;
  statusEl.textContent = 'Bitti';
}

// Görsel seç ve çıkarım başlat
predictBtn.addEventListener('click', async () => {
  const file = fileInput.files?.[0];
  if (!file) {
    alert('Lütfen bir görsel seçin.');
    return;
  }
  const img = new Image();
  img.onload = () => runInference(img);
  img.src = URL.createObjectURL(file);
});

// Sayfa yüklenince modeli hazırlayın (isteğe bağlı)
initModel().catch(err => {
  console.error(err);
  statusEl.textContent = 'Model yüklenirken hata oluştu.';
});

Performans İpuçları

- WebGPU genellikle WASM/WASM SIMD’e göre daha yüksek paralellik ve throughput sunar. Ancak küçük modellerde fark az olabilir. Model boyutu ve katman türleri sonucu etkiler.

- Modeli mümkün olduğunca küçük seçin (MobileNet, EfficientNet-Lite gibi). Büyük modeller hem ağdan indirmede hem de bellek kullanımında sorun çıkarabilir.

- İlk çıkarım (warm-up) genellikle daha yavaştır. Gerçek kullanıcı deneyimi için ikinci/üçüncü çıkarımı da ölçün.

- Vite yerine üretime alırken kodu küçültün ve model dosyasını CDN veya HTTP/2 ile hızlı sunun. Cache-Control başlıklarını doğru ayarlayın.

Sorun Giderme

- “WebGPU desteklenmiyor”: Tarayıcınızı güncelleyin veya chrome://flags içinde WebGPU ile ilgili bayrakları kontrol edin. Kurumsal politikalar GPU erişimini kısıtlayabilir.

- “Model giriş/çıkış adı uyuşmuyor” hatası: session.inputNames ve session.outputNames üzerinden gerçek isimleri alın, manuel isim yazmayın.

- Görselin renkleri veya sonuçlar beklenenden farklıysa, normalize adımlarını (mean/std) ve kanal sırasını (NCHW vs NHWC) model dokümantasyonuna göre doğrulayın.

- Bazı platformlarda WebGPU var ama belirli doku formatları kısıtlı olabilir. Fallback olarak WASM sağlayıcısını eklediğinizden emin olun.

Sonuç

WebGPU ve ONNX Runtime Web ile tarayıcıda makine öğrenimi artık gerçek bir seçenek. İstemci tarafında görsel sınıflandırma gibi görevlerde gizlilik, düşük gecikme ve çevrimdışı çalışma avantajları sunar. Bu rehberle temel bir iskelet kurdunuz; bundan sonra model çeşitliliğini artırabilir, etiket dosyaları ile daha anlaşılır sonuçlar gösterebilir, hatta Web Workers kullanarak arayüzü bloklamadan çoklu çıkarım senaryolarını deneyebilirsiniz. Kısacası, WebGPU sayesinde modern web uygulamaları, yapay zeka kabiliyetlerini kullanıcıya en yakın yerde, doğrudan tarayıcıda sunabiliyor.

2 Kasım 2025 Pazar

Tarayıcıda Yerel Yapay Zeka: WebGPU ve ONNX Runtime Web ile Görsel Sınıflandırma Nasıl Çalıştırılır?

Özet ve Neden Önemli?

Tarayıcıda çalışan yapay zeka, gizlilik, gecikme ve kullanıcı deneyimi açısından oyunun kurallarını değiştiriyor. WebGPU ile birlikte ONNX Runtime Web kullanarak bir görsel sınıflandırma modelini tamamen istemcide, yani kullanıcının cihazında çalıştırabilirsiniz. Böylece veriler sunucuya gönderilmez, ağ gecikmesi azalır ve uygulama çevrimdışı senaryolarda dahi işlevini sürdürür. Bu yazıda, sıfırdan bir ön yüz projesine WebGPU destekli ONNX Runtime Web ekleyerek, bir görüntüyü sınıflandırma adımlarını sade ama teknik açıdan tatmin edici bir şekilde ele alacağız.

Gereksinimler ve Mimari

WebGPU, modern tarayıcılarda donanım hızlandırmalı hesaplamaya erişmek için tasarlanmış, Vulkan/Metal/DX12 benzeri bir grafik ve hesap arayüzüdür. Chrome ve Edge’de kararlı; Safari’de Technology Preview; Firefox’ta ise genellikle bayrakla etkinleştirilmektedir. ONNX Runtime Web (kısaca ort), ONNX formatındaki modelleri tarayıcıda WASM, WebGL veya WebGPU üzerinde çalıştırır. Mimari şu şekilde işler: model dosyası (örn. mobilenetv3.onnx), tarayıcıya indirilir; preprocess aşamasıyla görüntü tensöre dönüştürülür; WebGPU yürütücüsü ile ileri besleme yapılır; sonuçlar postprocess ile insan tarafından anlaşılır etiketlere çevrilir.

Kurulum ve Dosya Yapısı

Basit bir yapı için bir HTML dosyası (index.html), bir JavaScript dosyası (app.js) ve model/etiket dosyalarınız (models/mobilenetv3.onnx, labels.txt) yeterlidir. Paket yöneticisi kullanacaksanız onnxruntime-web paketini ekleyebilir veya CDN üzerinden import edebilirsiniz. Yerel geliştirme için npm create vite@latest ile hafif bir iskelet kurup, npm i onnxruntime-web komutuyla kütüphaneyi dahil edebilirsiniz. Veya basit bir HTML sayfasında <script type="module"> ile ESM import yapabilirsiniz.

WebGPU’nun Etkinliği ve Geri Dönüş Planı

Önce tarayıcının WebGPU desteğini kontrol edin: if ('gpu' in navigator). ONNX Runtime Web oturumunu başlatırken yürütücüleri öncelik sırasına koyabilirsiniz: executionProviders: ['webgpu', 'webgl', 'wasm']. Böylece WebGPU yoksa WebGL, o da yoksa WASM’a otomatik düşülür. Bu yaklaşım, geniş bir cihaz/tarayıcı yelpazesini hedeflemenizi sağlar.

Modeli Yükleme ve Oturum Oluşturma

Bir InferenceSession başlatırken, graphOptimizationLevel ve preferredOutputLocation gibi seçeneklerle performansı iyileştirebilirsiniz. Örnek bir akış şu şekildedir: modeli fetch ile indirip await ort.InferenceSession.create çağırarak oturumu hazırlayın; etiket dosyasını (labels.txt) satır satır belleğe alın; giriş tensörünü uygun boyuta (ör. 224x224), kanal sırasına ve normalizasyona getirip Float32Array içine yerleştirin; ardından session.run(feeds) ile çıktı alın.

Ön İşleme: Doğru Tensör, Doğru Sonuç

Ön işleme aşaması, modelden iyi sonuç almak için kritiktir. Tipik olarak aşağıdaki adımları uygularsınız: resmi canvas üzerinde 224x224’e yeniden boyutlandırma; RGB kanallarını çıkarma; piksel değerlerini 0–1 aralığına ölçekleme; modelin beklediği ortalama ve standart sapma ile normalizasyon; kanal sırasını HWC’den CHW’ye çevirme. Son olarak tensörü new ort.Tensor('float32', data, [1, 3, 224, 224]) şeklinde oluşturursunuz.

Çıktının İşlenmesi ve Etiketleme

Modelden alınan ham skorları (logit) softmax ile olasılığa çevirmek, ardından en yüksek değere sahip sınıfı ve olasılığını bulmak temel adımdır. Etiket dosyanızla eşleyip kullanıcıya en olası ilk üç sonucu gösterebilirsiniz. Basit bir kullanıcı arayüzü için bir dosya yükleme alanı ve sonuç listesini güncelleyen kısa bir fonksiyon yeterlidir.

Performans İpuçları

1) WebGPU seçimi: Cihaz destekliyse WebGPU belirgin hız sağlar. 2) Kantizasyon: INT8 veya FP16 kantize modeller daha küçük ve hızlıdır; doğruluk/performans dengesini ölçün. 3) Toplu işleme: Birden fazla görseli ardışık yerine mini-batch olarak çalıştırmak throughput’u artırabilir. 4) WASM ayarları: Geri dönüş halinde ort.env.wasm.numThreads gibi ayarlarla CPU tarafını hızlandırın. 5) IO binding: Gelişmiş senaryolarda giriş/çıkışları GPU belleğinde bağlamak kopyalama maliyetini düşürür. 6) Önyükleme: İlk yüklemede modeli önbelleğe almak (Service Worker, HTTP caching) deneyimi iyileştirir.

Uyumluluk ve Sorun Giderme

Eğer “WebGPU desteklenmiyor” uyarısı alırsanız tarayıcınızı güncelleyin veya geçici olarak WebGL/WASM geri dönüş yolu kullanın. CORS hataları için model ve etiket dosyalarınızı aynı origin’den servis edin veya uygun başlıkları ayarlayın. Bozuk sonuçlar genelde ön işleme hatalarından kaynaklanır: kanal sırası (CHW vs HWC), normalizasyon değerleri ve giriş boyutunu iki kez kontrol edin. Performans düşükse geliştirici araçlarında GPU işlem kullanımını izleyin; entegre GPU’larda FP16/INT8 kazancı değişebilir.

Gizlilik ve Güvenlik

Yerel çıkarım, görsellerin cihazdan çıkmaması sayesinde gizliliği güçlendirir. Yine de kullanıcı izni olmadan dosya okuma, kalıcı depolama veya kamera erişimi gibi API’ler kullanılmamalıdır. Büyük modeller için indirme boyutunu küçültmek (sıkıştırma, kantizasyon) hem veri kullanımı hem de ilk yükleme süresini azaltır.

Sonuç

WebGPU ve ONNX Runtime Web ile tarayıcıda görsel sınıflandırma, artık bir prototipten öteye geçmiş durumda. Doğru model, sağlam ön işleme ve akıllı geri dönüş stratejileriyle, yüksek performanslı ve gizliliğe saygılı deneyimler oluşturabilirsiniz. Küçük bir demoyla başlayın; ardından etkileşimli görsel arama, canlı kamera üzerinde etiketleme veya tamamen çevrimdışı çalışan PWA gibi senaryolara genişleyin. Gelecek, kullanıcıların cihazında—ve siz bugün bunun temelini atabilirsiniz.