TensorFlow.js ile Javascript Kullanarak Yapay Zeka Geliştirin

Starzz

Üye
21 Haz 2015
238
58
tensorflow-js-logo-social.png

TensorFlow.js ile Yapay Zeka Geliştirmek

Merhaba dostlar. Bu yazımda sizlere TensorFlow.js kullanarak nasıl webde yapay zeka uygulamaları geliştirebilirsiniz onu anlatıyor olacağım. Öncelikle nedir bu TensorFlow bununla başlayalım.

Nedir Bu TensorFlow ?

Tensorflow, Google tarafından yıllar süren bir çalışma sonucunda oluşturulmuş, yapay zekanın derin öğrenme çalışmaları yapan geliştiriciler için üretilmiş, 2015 yılından beri kullanıcıların kullanımına açılmış açık kaynaklı bir kütüphanedir. İlk olarak sadece Python kullanılarak geliştirilmiş olan bu framework, günümüzde Pyhton’un yanında JavaScript, R, C#, C++ gibi akıllara gelebilecek en popüler yazılım dilleri tarafından desteklenmiş durumdadır. Yazılım dillerinin bu desteği TensorFlow’u herhangi bir yazılım diline hakim olan yazılım geliştiricilerin rahat bir şekilde kullanmasına olanak sağlamaktadır. TensorFlow’un bu kadar bilinen ve kullanılan bir kütüphane olmasının da temel sebebi budur.

TensorFlow'u anladık. Bu yazıda ise üstünde duracağımız konu bu kütüphanenin Javascript desteği olacak. Artık web geliştiricileri içinde Yapay Zekanın önü açılmış oldu :)

Eğer işin sıkıcı tarafını anladıysak şimdi gelin ufak bir örnek yaparak konuyu daha iyi anlamaya çalışalım.


Let's GO!

Burada yapacağımız örnek Yüz İfadelerini tahmin etmek. Bunun için uygulamaya bir fotoğraf vereceğiz ve ondan fotoğraftaki insana hangi duygu hakimse bize onu söyleyecek.

Şimdi burada bazı adımlar var bunlar için sırayla gidelim.


1) Image Prep

Burada amaç fotoğrafı yazılım anlayacağı formata sokmak. Bizler gözlerimizle normal bir şekilde gözlem yapıp, bu gözlemleri sonuçlandırabiliyoruz ancak yazılımlar bu şekilde çalışmaz. Onların daha farklı standartları vardır. Bu adımda Yazılımın standardına uygun fotoğraflar initilaze etmek.
JavaScript:
import { tf } from './tf'

const NORMALIZATION_OFFSET = tf.scalar(127.5)

export const prepImg = (img, size) => {
  const imgTensor = tf.fromPixels(img)

  const normalized = imgTensor
    .toFloat()
    .sub(NORMALIZATION_OFFSET)
    .div(NORMALIZATION_OFFSET)

  if (imgTensor.shape[0] === size && imgTensor.shape[1] === size) {
    return normalized
  }

  const alignCorners = true
  return tf.image.resizeBilinear(normalized, [size, size], alignCorners)
}

export const rgbToGrayscale = async imgTensor => {
  const minTensor = imgTensor.min()
  const maxTensor = imgTensor.max()
  const min = (await minTensor.data())[0]
  const max = (await maxTensor.data())[0]
  minTensor.dispose()
  maxTensor.dispose()

  const normalized = imgTensor.sub(tf.scalar(min)).div(tf.scalar(max - min))

  let grayscale = normalized.mean(2)

  return grayscale.expandDims(2)
}

Burada pikselleri [0, 255] ile [-1, 1] boyutları arasına alarak ml modelleri uygun hale getirdik.

2) Face Detection

Duyguları belirlemeden önce görüntüdeki insanları/yüzleri bulmalıyız. Bunun için yüz tanıma için Tensorflow.js üzerine kurulmuş bir kitaplık olan face-api.js kullanıyoruz.

JavaScript:
import * as faceapi from 'face-api.js'

const MODEL_PATH =
  `${process.env.PUBLIC_URL}/static/models/face/` +
  'mtcnn_model-weights_manifest.json'

const PARAMS = {
  minFaceSize: 50,
  scaleFactor: 0.709,
  maxNumScales: 10,
  scoreThresholds: [0.7, 0.7, 0.7],
}

export class FaceFinder {
  constructor(path = MODEL_PATH, params = PARAMS) {
    this.path = path
    this.params = params
  }

  async load() {
    this.model = new faceapi.Mtcnn()
    await this.model.load(this.path)
  }

  async findFaces(img) {
    const input = await faceapi.toNetInput(img, false, true)
    const results = await this.model.forward(input, this.params)
    const detections = results.map(r => r.faceDetection)

    return { input, detections }
  }

  async findAndExtractFaces(img) {
    const { input, detections } = await this.findFaces(img)
    const faces = await faceapi.extractFaces(input.inputs[0], detections)

    return { detections, faces }
  }
}

Face Detection kısmı ile alakalı daha fazla şeyi merak ediyorsanız şu makaleyi inceleyebilirsiniz.

3) Emotion Classification

Şimdi birincil aktivite zamanı, duyguları sınıflandırmak. Bunun için, yedi duygusal durumdan (Kızgın, İğrenme, Korku, Mutlu, Üzgün, Sürpriz, Nötr) uygulama tarafından kategorize edilen yüzlerin görüntülerini içeren FER-2013 veri kümesinde eğitilmiş açık kaynaklı bir CNN modeli kullanıyorum . Bu model Python'da oluşturuldu, bu yüzden Keras modelini web dostu bir biçime dönüştürmek için bu tfjs dönüştürücü aracını kullandım.

Modellere erişmek için
buraya tıklayın.

4) FrontEnd

Geldik projemizin son kullanıcıyı ilgilendiren kısma. Burada React kullanarak bir app.js yazdım ve yaptığım işlemlerin görüntüsünü ekrana aldım kısacası.

JavaScript:
import debounce from 'lodash.debounce'
import React, { Component } from 'react'
import Dropzone from 'react-dropzone'

import Footer from './Footer'
import Header from './Header'
import Message from './Message'
import Results from './Results'

import sampleImg from '../img/sample.jpg'
import { FaceFinder } from '../ml/face'
import { EmotionNet } from '../ml/models'
import { readFile, nextFrame, drawBox, drawText } from '../util'

class App extends Component {
  state = {
    ready: false,
    loading: false,
    imgUrl: sampleImg,
    detections: [],
    faces: [],
    emotions: [],
  }

  componentDidMount() {
    this.initModels()
    window.addEventListener('resize', this.handleResize)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize)
  }

  initModels = async () => {
    const faceModel = new FaceFinder()
    await faceModel.load()

    const emotionModel = new EmotionNet()
    await emotionModel.load()

    this.models = { face: faceModel, emotion: emotionModel }
    this.setState({ ready: true }, this.initPredict)
  }

  initPredict = () => {
    if (!this.img || !this.img.complete) return
    this.setState({ loading: true })
    this.analyzeFaces()
  }

  handleImgLoaded = () => {
    this.clearCanvas()
    this.analyzeFaces()
  }

  handleResize = debounce(() => this.drawDetections(), 100)

  handleUpload = async files => {
    if (!files.length) return
    const fileData = await readFile(files[0])
    this.setState({
      imgUrl: fileData.url,
      loading: true,
      detections: [],
      faces: [],
      emotions: [],
    })
  }

  analyzeFaces = async () => {
    await nextFrame()

    if (!this.models) return

    // get face bounding boxes and canvases
    const faceResults = await this.models.face.findAndExtractFaces(this.img)
    const { detections, faces } = faceResults

    // get emotion predictions
    let emotions = await Promise.all(
      faces.map(async face => await this.models.emotion.classify(face))
    )

    this.setState(
      { loading: false, detections, faces, emotions },
      this.drawDetections
    )
  }

  clearCanvas = () => {
    this.canvas.width = 0
    this.canvas.height = 0
  }

  drawDetections = () => {
    const { detections, emotions } = this.state
    if (!detections.length) return

    const { width, height } = this.img
    this.canvas.width = width
    this.canvas.height = height

    const ctx = this.canvas.getContext('2d')
    const detectionsResized = detections.map(d => d.forSize(width, height))

    detectionsResized.forEach((det, i) => {
      const { x, y } = det.box
      const { emoji } = emotions[i][0].label

      drawBox({ ctx, ...det.box })
      drawText({ ctx, x, y, text: emoji })
    })
  }

  render() {
    const { ready, imgUrl, loading, faces, emotions } = this.state
    const noFaces = ready && !loading && imgUrl && !faces.length

    return (
      <div className="px2 mx-auto container app">
        <Header />
        <main>
          <div className="py1">
            <Dropzone
              className="btn btn-small btn-primary btn-upload bg-black h5"
              accept="image/jpeg, image/png"
              multiple={false}
              disabled={!ready}
              onDrop={this.handleUpload}
            >
              Upload image
            </Dropzone>
          </div>
          {imgUrl && (
            <div className="relative">
              <img
                ref={el => (this.img = el)}
                onLoad={this.handleImgLoaded}
                src={imgUrl}
                alt=""
              />
              <canvas
                ref={el => (this.canvas = el)}
                className="absolute top-0 left-0"
              />
            </div>
          )}
          {!ready && <Message>Loading machine learning models...</Message>}
          {loading && <Message>Analyzing image...</Message>}
          {noFaces && (
            <Message bg="red" color="white">
              <strong>Sorry!</strong> No faces were detected. Please try another
              image.
            </Message>
          )}
          {faces.length > 0 && <Results faces={faces} emotions={emotions} />}
        </main>
        <Footer />
      </div>
    )
  }
}

export default App


Burada tanımlanan yüzlere canvas kullanarak kutular koyuyuorum ve buradan duygu anlama işlemi devam ediyor.



emotions.png
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.