Ruby로 얼굴 데이터 세트 NMF(비음수 매트릭스 인자 분해)

안녕하세요.
NMF 연습으로 얼굴 데이터 세트를 만들어 봤습니다.
 

루마르가 뭐예요?


https://github.com/yoshoku/rumale
루비의 머신러닝용 라이브러리.기계 학습의 각종 알고리즘이 모두 갖추어져 있다.
*

얼굴 이미지 데이터 세트 준비


IT의 Poggio Lab에서 공개한 Face Dataset을 사용합니다.
공식 홈페이지는 http://poggio-lab.mit.edu/FaceData2.html이지만 열 수 없습니다.
StackExchange의 Is the CBCL FACE DATABASE available?
에서 기술한 장면은 다음과 같은 절차를 이용하여 명세표를 작성하여 개념 디자인에서 체량의 부피를 분석하도록 한다.web.archive.org URL

데이터 세트 가져오기


작업 디렉토리를 만듭니다.
mkdir rumale-nmf-face # 名前は何でもいい
cd rumale-nmf-face
다운로드한 압축 파일을 rumale-nmf-face 디렉터리에 놓고 압축을 적당히 풀면 다음과 같은 디렉터리로 구성됩니다.
tree faces/ -L 3
faces/
├── README
├── face.test
│   └── test
│       ├── face
│       └── non-face
├── face.train
│   └── train
│       ├── face
│       └── non-face
├── faceall
├── rumale-nmf
├── svm.test.normgrey
└── svm.train.normgrey

어렵기 때문에 2429개의train의face 데이터 집합과 472개의test의face 데이터 집합을 정리했다.
mkdir faceall
cp faces/face.train/train/face/*.pgm faceall
cp faces/face.test/test/face/*.pgm faceall
모두 몇 개의 서류가 있는지 확인해 보겠습니다.
ls -1 faceall | wc -l
# 2901
이 파일들은 pgm 파일입니다.pgm는 스스로 팀으로 전환하기 위해 노력할 수 있다
편리한 라이브러리만 부르면 돼요.이럴 때를 위해 젬을 만드는 사람이 세상에 있으니까 사용하게 해주세요.
gem install pnm
그림에서 행렬을 꺼내보세요.
require 'pnm'

f = Dir.glob("faceall/*.pgm").first

img = PNM.read(f)
p img.pixels
루비 수조를 보여주면 좋을 거야.

Ruby 및 Gtk로 이미지 표시


GUI 제작 연습도 어려워요. 루비-gnome으로 얼굴 이미지를 표시하는 GUI 창을 만들어 보세요.
require 'gtk3'

w = Gtk::Window.new
w.title = "facebook"
w.set_size_request 300, 250
scw = Gtk::ScrolledWindow.new
scw.set_policy(:never, :automatic)
flowbox = Gtk::FlowBox.new

Dir.glob("faceall/*.pgm").each do |file_path|
  pixbuf = GdkPixbuf::Pixbuf.new(file: file_path)
  image = Gtk::Image.new(pixbuf: pixbuf)
  flowbox.add image
end

scw.add flowbox
w.add scw
w.show_all
scw.signal_connect(:destroy){Gtk.main_quit}
Gtk.main
이런 느낌인가요?스스로 창을 만들지 않아도 뷰어로 목록을 보면 차이가 많지 않다.
PNM
나 좀 무서워.

Rumale에서 NMF 실행

require 'pnm'
require 'rumale'

samples = Dir.glob("faceall/*.pgm").map do |f|
  begin
    image = PNM.read(f)
    pixels =image.pixels
    pixels.flatten
  rescue
    puts "can not read #{f}"
  end
end

samples = Numo::DFloat[*samples]

decomposer = Rumale::Decomposition::NMF.new(n_components: 49, max_iter: 200)
representation = decomposer.fit_transform(samples)       # 今回は使わない
components = decomposer.components
inversed = decomposer.inverse_transform(representation)  # 今回は使わない

File.binwrite("components.dat", Marshal.dump(components))

결과를 가시화합시다.이것도 여러 가지 방법을 생각해 낼 수 있다. 이번에는 component를 NMF 파일로 저장하고 아까 창을 살짝 개조해서 표시해 보자.연습과 동시에 Ruby/GTK로 창을 만들고 일부러 GUI를 만들고 싶지 않은 사람은 NMF의 Components를 PGM 이미지의 단락으로 바꾸는 곳만 실행하고 뷰어로 pgm 이미지를 보면 된다.
require 'gtk3'
require 'fileutils'
require 'numo/narray'
require 'pnm'

### NMFのComponentsをPGM画像に変換する
FileUtils.mkdir_p 'nmf_face'
components = Marshal.load(File.binread('components.dat'))
49.times do |i|
  pixels = components[i, true].reshape(19, 19)
  pixels = ((pixels / pixels.max) * 255).cast_to(Numo::UInt8).to_a
  image = PNM.create(pixels)
  image.write("nmf_face/component#{i}.pgm")
end

### GUI ###
w = Gtk::Window.new
w.title = '👫Facebook👍'
w.set_size_request 400, 400

notebook = Gtk::Notebook.new

def create_page(path)
  scw = Gtk::ScrolledWindow.new
  scw.set_policy(:never, :automatic)
  flowbox = Gtk::FlowBox.new

  Dir.glob(path).each do |file_path|
    pixbuf = GdkPixbuf::Pixbuf.new(file: file_path)
    # やや画像のサイズが小さいので200%に拡大する
    pixbuf_2x = pixbuf.scale_simple(pixbuf.width * 2, pixbuf.height * 2, :bilinear)
    image = Gtk::Image.new(pixbuf: pixbuf_2x)
    flowbox.add image
  end
  scw.add flowbox
  scw
end

notebook.append_page(create_page('faceall/*.pgm'), Gtk::Label.new('CBCL FACE DATABASE'))
notebook.append_page(create_page('nmf_face/*.pgm'), Gtk::Label.new('NMF'))

w.add notebook
w.show_all
w.signal_connect(:destroy) { Gtk.main_quit }
Gtk.main
이렇게 된 기분이야.괜찮지 않아요?


수학적으로 상세한 상황은 분명하지만 인터넷의 정보에 따르면 NMF는 전체 국면에서 가장 좋은 해가 아니라 국부적인 해를 구한다.이 얼굴의 견본은 아니지만 실행해 보면 처음에 얻을 만한 결과에 따라 큰 변화가 있을 것이다.나는 이 점에 주의해야 한다고 생각한다.
이 보도는 여기서 끝난다.
ai.mit.edu의 링크는 운이 좋지 않아 중간에 멈추었다.구글 콜라비 (미국 방문) 라면 끝까지 다운로드할 수 있을 것 같습니다.5월 말에 디프는 두 링크된 파일에 차이가 없음을 확인했다. 

좋은 웹페이지 즐겨찾기