Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ieee0824/132811486227dfca0b4b to your computer and use it in GitHub Desktop.
Save ieee0824/132811486227dfca0b4b to your computer and use it in GitHub Desktop.

この記事は高知工科大 Advent Calendar 2015の21日目の記事です.

機械学習をやってみる

大学生といえば機械学習が大好きですよね?
なので今日は機械学習についてゆるふわな感じで触っていきます.
先に言い訳しときますがプログラムを書き始めたのが21時過ぎなので学習データ用意出来てません.

機械学習に使われているイメージのある言語

  • Python
  • R言語

数値計算のライブラリが充実しているため結構機械学習に使われている印象があります.
実際ニューラルネット実装でググるとこんな感じで出てきます.

Python人気ですね.
しかし今回はPythonもR触る気無いのであしからず.

Go言語で機械学習を触る

工学部の学生なら一度はGo言語触ったことがあると思います.
触ったこと無い人もいると思うので書いておくとGo言語はGoogleによって開発された言語です.
主な特徴として、軽量スレッディングのための機能、Pythonのような動的型付け言語のようなプログラミングの容易性、などがあります.
ちょっと前まではOS X, Linux, Windowsのみのサポートでしたが最近はAndroid, iOSもサポートしています.

Go言語の良い所

  • コンパイラ言語である
  • 並列プログラミングが容易である
  • Pythonに近い乗りでコーディングできる
  • キャラクターが可愛い

とりあえず機械学習を触ってみる

今回何も無いところから機械学習を触っていくつもりは無いのでライブラリを使います.
go-neuralというライブラリを使っていきます.
go get -u github.com/NOX73/go-neuralでライブラリを取得します.
使い方は非常に簡単です.
公式のREADME.mdに書いてあるとおりに使えば基本的には動きます.

package main

import (
	"fmt"
	"github.com/NOX73/go-neural"
)

func main() {
	n := neural.NewNetwork(9, []int{9, 9, 4})
	n.RandomizeSynapses()
	result := n.Calculate([]float64{0, 1, 0, 1, 1, 1, 0, 1, 0})
	fmt.Println(result)
}

簡単ですね.
細かい使い方は実装を見ればわかると思うので割愛します.

画像処理をやらせてみる

Hello world的なことをやっても面白く無いので画像処理をやってみましょう.
画像を読み込む処理を書いていきます.

ファイルを読み込む

func openFile(name string) (*os.File, error) {
	return os.Open(name)
}

formatを判定する

func getFormat(file *os.File) string {
	bytes := make([]byte, 4)
	n, _ := file.ReadAt(bytes, 0)
	if n < 4 {
		return ""
	}
	if bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47 {
		return "png"
	}
	if bytes[0] == 0xFF && bytes[1] == 0xD8 {
		return "jpg"
	}
	if bytes[0] == 0x47 && bytes[1] == 0x49 && bytes[2] == 0x46 && bytes[3] == 0x38 {
		return "gif"
	}
	if bytes[0] == 0x42 && bytes[1] == 0x4D {
		return "bmp"
	}
	return ""
}

formatに合わせてデコードする

func readBMP(io *os.File) (image.Image, error) {
	return bmp.Decode(io)
}

func readPNG(io *os.File) (image.Image, error) {
	return png.Decode(io)
}

func readJpeg(io *os.File) (image.Image, error) {
	return jpeg.Decode(io)
}

func readGIF(io *os.File) (image.Image, error) {
	return gif.Decode(io)
}

func openFile(name string) (*os.File, error) {
	return os.Open(name)
}

ファイル名入れたらimage.Imageで返してもらう

func decodeImage(name string) (image.Image, error) {
	io, err := openFile(name)
	if err != nil {
		return nil, err
	}
	imageFormat := getFormat(io)

	switch imageFormat {
	case "bmp":
		return readBMP(io)
	case "jpg":
		return readJpeg(io)
	case "png":
		return readPNG(io)
	case "gif":
		return readGIF(io)
	default:
		return nil, errors.New("can not read file.")
	}
}

オリジナルの画像と圧縮した画像を学習させる

func isOutOfImage(x int, y int, img image.Image) bool {
	rect := img.Bounds()
	if x < 0 && y < 0 {
		return true
	} else if rect.Max.X <= x && rect.Max.Y <= y {
		return true
	}
	return false
}

func getRGBA256(x int, y int, img image.Image) (uint8, uint8, uint8, uint8) {
	r, g, b, a := img.At(x, y).RGBA()
	return uint8(r), uint8(g), uint8(b), uint8(a)
}

func learnColor(cmp image.Image, org image.Image, networks []neural.Network) []neural.Network {
	rect := org.Bounds()
	bufR := make([]float64, 9)
	bufG := make([]float64, 9)
	bufB := make([]float64, 9)

	for x := 0; x < rect.Max.X; x++ {
		for y := 0; y < rect.Max.Y; y++ {
			cnt := 0
			for i := -1; i <= 1; i++ {
				for j := -1; j <= 1; j++ {
					if isOutOfImage(x+i, y+j, cmp) {
						bufR[cnt] = 0
						bufG[cnt] = 0
						bufB[cnt] = 0
					} else {
						r, g, b, _ := getRGBA256(x+i, y+j, cmp)
						bufR[cnt] = float64(r) / 100
						bufG[cnt] = float64(g) / 100
						bufB[cnt] = float64(b) / 100
					}
					cnt++
				}
			}
			r, g, b, _ := getRGBA256(x, y, org)
			learn.Learn(&networks[0], bufR, []float64{float64(r) / 100}, 0.01)
			learn.Learn(&networks[1], bufG, []float64{float64(g) / 100}, 0.01)
			learn.Learn(&networks[2], bufB, []float64{float64(b) / 100}, 0.01)

		}
	}

	return networks
}

学習した値から計算する

func filter(img image.Image, networks []neural.Network) image.Image {
	rect := img.Bounds()
	ret := image.NewRGBA(rect)
	for x := 0; x < rect.Max.X; x++ {
		for y := 0; y < rect.Max.Y; y++ {
			bufR := make([]float64, 9)
			bufG := make([]float64, 9)
			bufB := make([]float64, 9)
			cnt := 0
			for i := -1; i <= 1; i++ {
				for j := -1; j <= 1; j++ {
					if isOutOfImage(x+i, y+j, img) {
						bufR[cnt] = 0
						bufG[cnt] = 0
						bufB[cnt] = 0
					} else {
						r, g, b, _ := getRGBA256(x+i, y+j, img)
						bufR[cnt] = float64(r) / 100
						bufG[cnt] = float64(g) / 100
						bufB[cnt] = float64(b) / 100
					}
					cnt++
				}
			}
			r := networks[0].Calculate(bufR)
			g := networks[0].Calculate(bufG)
			b := networks[0].Calculate(bufB)
			fmt.Println(r, g, b)
			c := color.RGBA{R: uint8(r[0] * 100), G: uint8(g[0] * 100), B: uint8(b[0] * 100), A: 0xff}
			ret.Set(x, y, c)
		}
	}
	return ret
}

とりあえず動かしてみた

30分ぐらいで急いで書いたからバグあるかも
あと学習量たりなさすぎて微妙だが
とりあえず動かしてみた感じなんとなくそれっぽく動いてるんじゃないかと

とりあえずもう少し学習データ用意していろいろ試してみたい.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment