読者です 読者をやめる 読者になる 読者になる

Tech Tac

機械学習とか統計とかデバイスについてとか

Macのクラムシェル機能を使うと作業スペース(物理)が広がって便利

クラムシェルって言う言葉忘れたり、クラムシェル発動条件みたいなの忘れるのでメモ的な感じ

クラムシェルって?

クラムシェルモードとは、Macの内蔵ディスプレイを閉じた状態で外部ディスプレイのみ使うモードのこと

クラムシェルの条件

  • 電源が刺さっている
  • 外部キーボード、外部マウスが接続されている
  • 当然だけど、外部ディスプレイが接続されている

上記の条件を満たした状態でMacBook閉じると勝手にクラムシェルモードになります。

何が便利なの?

タイトルにもある通り、物理的な作業スペースが広がるので本を広げながらとか、メモやノート取りながら(メモはアナログ派向け)とかの作業がはかどります。 外部ディスプレイが二枚ある場合に、ぼくは内蔵ディスプレイってそんなに見ない+Macで論文おいたりするスペースが狭いとなったりしたときにクラムシェルしたら便利でした。

実際にラボで使っている様子

右側にいつもMacをおいていたのですが、そうすると右側のスペースはMacが占めていてあんまり使えないという状況でした。
クラムシェルを使うことによってちょっと広くなったので満足。
↓はMacをディスプレイの下に収納している様子。これで省スペース化可能。

Macの置く場所ですが、僕が研究室で使っているのは

リヒトラブ 机上台 TEFFA A7330-24 黒

リヒトラブ 机上台 TEFFA A7330-24 黒

ディスプレイの高さおんなじやしこんなの使わないと言うとき、僕はお家では以下を使っています

まとめたけど…

ここに書いてることほぼそのままなので一次情報がほしい方はこちらから。

ChainerのTrainerを使ってFineTuning

どうもこんにちは

chainerなんか早くなったらしいですね。

とても素晴らしい技術力だと思いますが、個人的には高速化よりも詳しい使い方が書いたドキュメントや日本語ドキュメントの充実に力を入れてほしい気がします。
(GPU128枚も持ってないし…)
128枚もGPUを使って何かするようなところって大きな企業かでかい研究機関しかないと思うし、そういったところが使うかと言うと使わない気もする。 PyTorchとかchainerに似ているフレームワークも出てきていて正直chainerどうなるんだろうという感じはしていますが、PaintsChainerとかあったり一応日本では流行ってるみたいなので使ってみました。

Trainer

Trainerってなんだって話ですが、今まではバッチ処理を自分で書いたりしなければならなかったのがTrainerによって抽象化されて書く必要がなくなりました。 いまどれだけの進捗でどれくらいのlossになっててAccuracyはどれくらいだと言うことも割りと簡単にできるようになったみたいなので今回はこのTrainerを使ってみたいと思います。 学習させるところまでできたので記録としてかいてあります。 間違ってるところとか、こういうふうに書いたほうがかっこいいぜみたいなのあったら教えていただけるとありがたいです。

使い方

上のサンプルコードを参考に書いていきます。詳しいことはこのサンプルとドキュメントを見るとわかりやすいかと思います。 まず、事前にやっておくこととして、FineTuningをしたいのでモデルの重みを取ってきておきます。 modelはこちらにたくさんあるので好きなのを選びましょう。

caffeのモデルですが、chainerではcaffeのモデルをロードできるような仕組みがCaffefunctionと言うかたちで実装されています。 caffefunctionの詳しい使い方は今回書きませんが、caffeのモデルを読み込むのはすごく時間がかかるので、一度読み込んだらPickleなどでdumpしておきましょう。 重みの読み込みは以下ののコードの場合load_model.pyということに書いてあります。重みの読み込みはこちらで書いていることと同じことを行っています。

手順としては、
重みを読み込む→トレーニングセットと、バリデーションセットに分ける→optimizer,updaterの設定をする→trainerでトレーニング

と言った感じです。 Trainerで学習させるときにGPUを使う場合はモデルにたいしてto_gpu()を行う必要があります。ここで結構ハマりました。

import chainer
import pickle
import chainer.links as L
from chainer import training
from chainer.training import extensions
from preprocess import ImagePreprocess
import vgg16
from load_model import load_caffe_model
import os
import pandas as pd


def trainer(csv_file, root, batch_size, lorderjob, image_size, gpu):

    # load model
    model = vgg16.Vgg16()
    model_weight = pickle.load(open('../data/models/vgg16model', 'rb'))
    load_caffe_model(model_weight, model)
    model = L.Classifier(model)
    print('finish loading model')

    if gpu >= 0:
        chainer.cuda.get_device(0).use()
        model.to_gpu()

    # create train set and validation set
    csv_data = pd.read_csv('../data/train.tsv', delimiter='\t')
    dataset = []
    for r in csv_data.iterrows():
        dataset.append((r[1][0], r[1][1]))
    train, val = chainer.datasets.split_dataset_random(dataset, 9000)
    train_data = ImagePreprocess(train, root, image_size)
    val_data = ImagePreprocess(val, root, image_size, False)

    train_iter = chainer.iterators.MultiprocessIterator(
        train_data, batch_size, n_processes=lorderjob
    )
    val_iter = chainer.iterators.MultiprocessIterator(
        val_data, batch_size, repeat=False, n_processes=lorderjob
    )

    # setup optimizer
    optimizer = chainer.optimizers.SGD()
    optimizer.setup(model)

    # setup updater and trainer
    updater = training.StandardUpdater(train_iter, optimizer, device=0)
    trainer = training.Trainer(updater, (10, 'epoch'), out='result')

    trainer.extend(extensions.Evaluator(val_iter, model, device=0))
    trainer.extend(extensions.dump_graph('main/loss'))
    trainer.extend(extensions.snapshot(), trigger=(5, 'epoch'))
    trainer.extend(extensions.snapshot_object(
        optimizer, 'optimizer_iter_{.updater.iteration}'), trigger=(5, 'epoch'))
    trainer.extend(extensions.LogReport())
    trainer.extend(extensions.PrintReport(
        ['epoch', 'main/loss', 'validation/main/loss',
         'main/accuracy', 'validation/main/accuracy']
    ), trigger=(1, 'epoch'))
    trainer.extend(extensions.ProgressBar(update_interval=10))
    trainer.run()

    print('Training is finished!')

DataMixinの拡張をして、画像をミニバッチごとに読み込む

import chainer
import random
import cv2


class ImagePreprocess(chainer.dataset.DatasetMixin):

    def __init__(self, dataset, root, img_size, random=True):
        self.base = chainer.datasets.LabeledImageDataset(dataset, root)
        self.img_size = img_size
        self.random = random

    def __len__(self):
        return len(self.base)

    def get_example(self, i):
        img_size = self.img_size
        image, label = self.base[i]
        image = image.transpose(1, 2, 0)
        image = cv2.resize(image, (img_size, img_size))
        image = image.transpose(2, 0, 1)
        _, h, w = image.shape

        if self.random:
            # Randomly imga region and flip the image
            if random.randint(0, 1):
                image = image[:, :, ::-1]

        image *= (1.0 / 255.0)  # Scale to [0, 1]
        return image, label

preprocess.pyというファイルにDatasetMixinクラスを拡張したものを作っています。このクラスを拡張して、get_exampleをいい感じにいじるとミニバッチごとに画像を読み込んでくれるのでメモリの節約をすることができます。 DataAugmentationもこれを使うことでできます。上のコードではエポックごとに画像をランダムでフリップさせることによって、画像のデータを増やすといったことをしています。

またこのクラスのオブジェクトをMultiprocessIteratorに渡すことでCPUでミニバッチ分の画像を読み込み、GPUで学習といったことができるようになります。

以上のようにすれば学習が進んでいくかと思います。 Trainerは抽象化されているので理解するのに少し時間がかかるかと思いますが、使えるようになると便利なので使っていくといいのではないでしょうか。 特に、CPUで画像読み込みながらGPUで学習するとかいったコードを自分で書くのは大変そうなのでそのあたりもTrainer使うと便利そうです。

HHKB type-Sを買った

先日HHKBのBTバージョンが壊れてしまい、今サポートに回しているのですが、大変不便なのでもう一つ買っておこうということで買いました。 試打も兼ねてこちらの記事を書いています。

PFU Happy Hacking Keyboard Professional2 Type-S 英語配列/白 PD-KB400WS

PFU Happy Hacking Keyboard Professional2 Type-S 英語配列/白 PD-KB400WS

BTバージョンとの比較も兼ねて書いていこうかと思います。

HHKB BTに関して

HHKBのブルートゥースバージョンは半年ほど前に買ったのですが、そちらは頻繁にチャタリングっていうんですかね? キーを押していないのに押している判定になって、永遠に同じキーが押されている判定になったり、ひどいときはバックスペースがソレになって一生懸命書いたコードが どんどん白紙と化していくのを眺めることしかできなかったりと色々と問題が多かったです。

そして、半年ほど使用した後に文鎮化…

他にも同じ症状の方もいるようで、サポートに連絡したら、ファームウェアアップデートをすれば治るとのことでPFUに一旦キーボードを送る必要があるそう。 ソレが終わったら治るらしい。期待して待っておこう。

そんなわけで…

現状僕の手元にあるキーボードがREALFORCEと、Macの標準のキーボードしかなかったのです。
Realforceに関しては、昔使っていた日本語配列のもの。英字配列に慣れてしまった今となってはとても使えません。

Mac標準キーボードに関してはLate2016から変更されたキーボードのストロークの浅さに全然慣れず、指がとても痛くなりとてもじゃないけどコーディングとかいってられなかった。

いつ戻ってくるかわからないものを待っていても仕方ないのでTypeSを購入することにした。 f:id:ytac8:20170209113936j:plain

感想みたいなもの

無刻印!!!!
かっちょいい!打鍵感もまぁよいです。個人的にはもう少し深くてもいいかなぁと。音に関してはBTタイプのHHKBよりも格段に静かです。 Realforceと同じくらいかな?個人的な打鍵感としてはBT版とは全然違ってこっちのほうが好きです。リアルフォースに近くなった感じがする。 というか同じ?ちょっと僕程度のレベルではわからない。
BT版は持ち運びに便利なのが魅力かと思っていたが、正直こっちのほうがBT版よりも軽いし持ち運びしやすいと思う。 BT買うならTypeS買ったほうがいいような気もしないでもない。
BT版は戻ってきたらこれからはお家専用機として使っていこうと思っている。

3時間くらいカタカタしてみての感想なので、まだ疲れるかとかはわからないけどとても満足している。 この良いキーボードに見合うようにたくさんコードかけるようにしたい。

追記

追記: BTのHHKBが帰ってきたが、チャタリングの現象は全然直ってなかった。むしろひどくなっている感じがした。 もう一度問い合わせ中

追記2: 現在、改造した?試用機を送ってもらった。こちらはなんの問題もなく動いている模様です。 自分のキーボードを返送して、もどってくるまでは試用機の方を使っていこうと思います。 チャタリングがなければかなり使い心地はいい。

追記3 キーボードが帰ってきました。 チャタリングも起こらなくなり快適にタイピングすることができます。 静音タイプもいいですが、タイプした時にこのカタカタと鳴る音が心地良いですね。

追記4:しばらく使ってみているとまたチャタリングするようになった…BT版はしばらく様子見した方がいいと思います。

追記5:しばらく使ってみたのですが、チャタリングだいぶ落ち着いたのかな?という感じです。ほぼほぼストレスはなくなった感じです。
Macのバージョンアップのおかげかもしれないけどよくわからない。