TensorFlowのtf.contrib.layers.batch_normの注意点

TensorFlowのtf.contrib.layers.batch_normは他のtf.contrib.layersの関数(conv2dfully_connectedなど)にnormalizer_fnパラメーターで渡すことができ、Batch Normalizationを含めひとつの関数呼び出しにまとめることができるのでコードがスッキリして便利です。

output = tf.contrib.layers.conv2d(
    inputs,
    num_outputs=128,
    kernel_size=4,
    stride=2,
    normalizer_fn=tf.contrib.layers.batch_norm,
    normalizer_params=params,
    trainable=True)

しかし、このbatch_normやtf.contrib.layersの関数にはいくつか重要な注意点があります。

batch_normがtf.GraphKeys.UPDATE_OPSに登録したopsの更新処理を忘れないようにする

batch_normのmoving_meanやmoving_varianceの更新に関するopsはtf.GraphKeys.TRAINABLE_VARIABLESではなくtf.GraphKeys.UPDATE_OPSに登録されます。このUPDATE_OPSに登録されたopsは、以下のようにoptimizerなどが走る前に明示的に更新する必要があります。

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
  train_op = optimizer.minimize(loss)

ドキュメントにも以下のような注意書きがありますが、青色のセクションに書かれているので、NoteというよりはFYIという風に見えて見逃しやすいので気をつけましょう。

Note : when training, the moving_mean and moving_variance need to be updated. By default the update ops are placed in tf.GraphKeys.UPDATE_OPS, so they need to be added as a dependency to the train_op. For example: (コード例に続く…)

tf.contrib.layers.batch_normのis_trainingパラメーターの設定を忘れないようにする

他のtf.contrib.layersの関数と違い、tf.contrib.layers.batch_normにはtrainableだけでなくis_trainingパラメーターもあります。

batch_norm(
    inputs,
    is_training=True,
    trainable=True,
    ...)

trainableはbatch_normの内部にあるvariablesをGraphKeys.TRAINABLE_VARIABLESに登録するかどうかを制御するためのboolパラメーターなのに対して、is_trainingはmoving_meanやmoving_varianceの挙動に関するboolパラメーターです。どちらもデフォルトでTrueですが、学習以外の時は明示的にFalseを設定する必要があります。特にis_trainingがTrueのままの場合、同じ入力に対してbatch_normが毎回違う出力をしてしまい、モデルの再現性がなくなる場合があるので注意が必要です。

tf.contrib.layersの関数にnormalizer_fn=tf.contrib.layers.batch_normを指定する場合はnormalizer_paramsも設定する

冒頭にも紹介したように、tf.contrib.layersの関数はnormalizer_fnパラメーターにbatch_normを指定することで、レイヤーの計算後にBatch Normalizationを適用してくれます。しかし、normalizer_fnはデフォルトでinputsパラメーターだけ指定して呼び出され、他のパラメーターはデフォルト引数が使われます。

# 期待した通りに動かない例
# conv2d自体にtrainable=Falseを指定してもbatch_normには渡されず、
# batch_normはデフォルト引数で呼ばれる(is_training=True, trainable=True)
is_training = False
output = tf.contrib.layers.conv2d(
    inputs,
    num_outputs=128,
    kernel_size=4,
    stride=2,
    normalizer_fn=tf.contrib.layers.batch_norm,
    trainable=is_training)

この問題は、normalizer_fnを指定したtf.contrib.layersの関数のnormalizer_paramsパラメーターを使うことで解決できます。

# 正しく動く例
# batch_normにis_training=Falseとtrainable=Falseが渡される
is_training = False
normalizer_params = {'is_training': is_training, 'trainable': is_training}
output = tf.contrib.layers.conv2d(
    inputs,
    num_outputs=128,
    kernel_size=4,
    stride=2,
    normalizer_fn=tf.contrib.layers.batch_norm,
    # batch_norm用のパラメーターを指定する
    normalizer_params=normalizer_params,
    trainable=is_training)

この挙動はドキュメントからだと分かりにくいので注意しましょう。

Deep Learningで「いらすとや風人間画像生成モデル」を作った話(DCGAN、Wasserstein GAN)

フリー素材サイト「いらすとや」に出てくる人間風の画像を自動生成するモデルをDeep Learningで作りました。実装にはGoogle製のライブラリ「TensorFlow」と機械学習アルゴリズムの「DCGAN」「Wasserstein GAN」を用いています。

以下は生成された人間画像のうちそれなりにきれいなものの一例です。頬のところが赤くなっていて何となく本家いらすとやの特徴を捉えられていると思います。

f:id:mickey24:20170630230846p:plain:w200 f:id:mickey24:20170701220955p:plain:w200 f:id:mickey24:20170701221012p:plain:w200 f:id:mickey24:20170701223928p:plain:w200

「いらすとや」とは?

いらすとや」は15,000種類以上のかわいいイラストを提供するフリー素材サイトです。皆さんもおそらく一度はどこかのWebページでいらすとやの画像が使われているのを見たことがあるのではないでしょうか。

実装した手法の概要

DCGAN、Wasserstein GANについて

人間画像生成モデルの学習にはDCGANとWasserstein GANを用いています。各アルゴリズムの詳細については既に他の方々が分かりやすい記事を書いていますのでそちらを参考にしてください。ここでは簡単な説明に留めます。

まず、GANはGenerative Adversarial Networkの略で、機械学習のアルゴリズムの一種です。「訓練データとGeneratorが生成したデータを見分けるDiscriminator」「Discriminatorを騙せるようなデータを出力するGenerator」を交互に競わせるように学習していき、最終的に訓練データに似たデータを生成できるGeneratorを作り上げることができます。

DCGANはDeep Convolutional GANの略で、GANを使いConvolutional Neural Network(CNN)を学習していく手法です。CNNを使うので画像生成に適用する事例が多いようです。論文ではBatch NormalizationやLeakyReLUといった工夫を用いることでGANによるCNNの学習が安定するとされています。

Wasserstein GANはGANの学習方法を改良したもので、Discriminator*1や目的関数を工夫することにより、GANの学習の収束しにくさやmode corruptionといった問題を軽減できるとされています。論文の著者本人がGithub上でPyTorchの実装を公開しています

Generator

Generatorは「Discriminatorを騙せるようないらすとや風人間画像を出力するCNNベースのモデル」です。Generatorへの入力は標準正規分布*2からサンプルされた40次元の実ベクトルで、ひとつの入力ベクトルごとに対応するひとつの画像がモデルから出力されます。出力画像サイズは64x64で、各ピクセルのR、G、Bの値はそれぞれ[-1, 1]の範囲で表されます。このピクセル値を[0, 255]の範囲にリスケールすることで最終的な出力画像を得ることができます。

f:id:mickey24:20170703004822p:plain

Discriminator

Discriminatorは「本物のいらすとやの画像とGeneratorが生成した画像を見分けることができるCNNベースのモデル」です。Discriminatorへの入力は64x64のRGB画像データです。各ピクセルのR、G、Bの値はそれぞれ[-1, 1]の範囲に正規化して入力します。出力はスカラー値で、Discriminatorが入力画像を本物のいらすとやの画像だと判定した場合は大きな値を、Generatorが生成した画像だと判定した場合は小さな値を出すように学習させます。

f:id:mickey24:20170703005841p:plain

GeneratorとDiscriminatorの学習

DCGAN・Wasserstein GANでは、GeneratorとDiscriminatorを交互に学習させていきます。

Generatorの学習の際にはDiscriminatorのパラメーターを固定し、以下の学習を行います。

  1. ベクトルzをサンプルしてGeneratorに与え、画像を出力する
  2. Generatorの画像をDiscriminatorに与え、スカラー値y_Gを出力する
  3. y_Gが大きな値となる画像を出力できるようにGeneratorのパラメーターを更新する

学習を続けていくと、理想的にはどんな入力ベクトルzを与えてもDiscriminatorを騙せるくらい本物っぽい画像が出てくるようになります(しかし実際はそんなに甘くない)。

f:id:mickey24:20170702001221p:plain

Discriminatorの学習時はGeneratorのパラメーターを固定し、以下の学習を行います。

  1. 訓練データからサンプルした本物のいらすとやの画像をDiscriminatorに与え、スカラー値y_Rを出力する
  2. ベクトルzをサンプルしてGeneratorに与え、画像を出力する
  3. Generatorの画像をDiscriminatorに与え、y_Gを出力する
  4. y_R - y_G *3が大きな値となるようにDiscriminatorのパラメーターを更新する

学習を続けていくと、理想的にはGeneratorがどんなに本物のいらすとやっぽい画像を出力するようになっても、Discriminatorは本物と偽物を見分けることができるようになります(しかし実際はそんなn)。

f:id:mickey24:20170703011334p:plain

学習や実装の詳細

ネットワーク構成や各パラメーターは主にDCGANとWasserstein GANの論文を参考にしていて、あまり変わったことはしていないと思います。コードも他の方々がGithub等で公開しているものと同じような感じで実装しています。

Generator、Discriminatorのネットワーク構成やパラメーター

Generatorのネットワーク構成は以下のようになっています。

f:id:mickey24:20170704003049p:plain

  • 転置畳み込み層(conv2d_transpose)*4のカーネルサイズは4、ストライドは2です。
  • Batch Normalizationは最初の全結合層と前3つの転置畳み込み層で適用しています。最後の転置畳み込み層では適用していません。
  • 活性化関数は、最初の全結合層と前3つの転置畳み込み層ではReLUを適用しています。最後の転置畳み込み層では出力を[-1, 1]にするためにtanhを適用しています。
  • dropoutは使っていません。

Discriminatorのネットワーク構成は以下のようになっています。

f:id:mickey24:20170703235458p:plain

  • 畳み込み層のカーネルサイズは4、ストライドは2です。
  • Batch Normalizationは後ろ3つの畳み込み層で適用しています。最初の畳み込み層と最後の全結合層では適用していません。
  • 活性化関数は、後ろ3つの畳み込み層ではLeakyReLUを適用しています。最初の畳み込み層と最後の全結合層では適用していません。
  • プーリング層やdropoutは使っていません。

訓練データ

訓練データは約15,000枚のいらすとや画像をクロールし、「ひとりの人間が載っていて背景色などがあまり複雑でない画像」約4000枚を手動フィルターして使っています。訓練データ数が非常に少ないので、論文になっているようなDCGANの適用事例と比べると難易度が高いタスクではないかと思います。

その他

学習時のbatch sizeは64、最終的なtraining step数は149,560ですが、50,000 stepsあたりからそれ程精度の変化が見られませんでした。また、Wasserstein GANの論文に倣い、勾配法はRMSProp、学習率は0.00005、weight clippingパラメーターは0.01を使いました。

ちなみに手元のMacBook Pro Late 2016だと学習に時間がかかり過ぎたので、Google Cloud Platformの無料枠$300を使い、Cloud ML EngineのCPUx1+GPUx1のマシンで学習させたところ、学習速度が5倍以上になりました(それでも100k steps学習するのに1〜2日程度)。ハイパーパラメーターを調整して複数の学習を走らせることを考えると、やはり機械学習をする上でGPU等のある程度の計算資源は必須だと思います。

学習経過

最初のうちはどんな入力に対してもランダムなモザイクのような画像が出力されます。

f:id:mickey24:20170704231029p:plain:w200

そこからだんだん出力画像が白くなっていき、1,000ステップあたりで髪の毛や人の肌っぽい色が目立ち始めてきます。しかし形は人間からは程遠いです。

f:id:mickey24:20170704231052p:plain:w200

1,500ステップくらいになるとより髪の色や肌っぽい色が強くなってきます。

f:id:mickey24:20170704231120p:plain:w200

4,000ステップくらいで何かしらの形が見え始めます。

f:id:mickey24:20170704231149p:plain:w200

7,000ステップくらいになると人の顔や髪の毛のような形が認識できるケースが増えてきます。

f:id:mickey24:20170704231208p:plain:w200

そこからしばらくは目や口みたいなものが顔みたいなものの中に現れたり、本当になんとも言えないぐちゃぐちゃなものが出力されたりと言った状況を繰り返します。50,000ステップくらいになると画像の粗さが減り、たまにいい感じの人間っぽい画像が出力されます。

f:id:mickey24:20170704232353p:plain:w200

だいたいこの時点で入力次第でモデルがいい画像を出力できるようになっていたようです。そこから先はあまり大きな変化は見られませんでした。

モデルを検証する

学習したモデルを手軽に確認してみるために、「TensorFlowによるDCGANでアイドルの顔画像生成 その後の実験など - すぎゃーんメモ」で紹介されているようなWeb UI(インスペクター)を実装し、様々な入力ベクトルに対応する出力画像を簡単に検証できるようにしてみました。以下はインスペクターでモデルを検証している時の動画です。

これを利用すれば、入力ベクトルのどの次元の値がどの画像の特徴を表しているのかが分かる…かもしれません。

ちなみに学習時の入力ベクトルは標準正規分布からサンプルしているので、ゼロベクトルに対応する出力画像は全ての人間画像の中間表現みたいになるのかなと思って見てみたら以下のような筆舌に尽くし難い画像が出てきました。

f:id:mickey24:20170701221943p:plain:w200

中間人間画像が必要な方はご自由にお使いください。

入力にバイアスを掛けていい画像を出やすくする

学習したモデルに適当な入力ベクトルを与えても、必ずしもきれいな画像が出てくるとは限りません。

f:id:mickey24:20170630230341p:plain:w200 f:id:mickey24:20170630230329p:plain:w200 f:id:mickey24:20170630230443p:plain:w200 f:id:mickey24:20170630230315p:plain:w200

DCGANなどの論文ではよく本物の写真みたいな画像が生成された例が出てくると思いますが、あれらもいい画像が出てくるまで入力を変えて頑張り続けた結果だと思います。

そこで、「TensorFlowによるDCGANでアイドルの顔画像生成 その後の実験など - すぎゃーんメモ」で紹介されているように、入力ベクトルにバイアスを掛けてモデルがいい画像だけを出力しやすくなるようにできるか試してみました。まず、いい画像が出るまでランダムな入力ベクトルをモデルに与え、画像を生成し続けます。そして、以下のようなよさげな画像が出たところで…、

f:id:mickey24:20170630230846p:plain:w200

その画像の入力ベクトルを保持しておきます。

[-1.0,-0.6,-0.8,-0.1,1.1,-0.7,-1.6,-1.1,0.8,0.1,-0.2,0.1,0.8,0.6,1.1,-0.9,-0.4,0.9,2.0,0.8,1.5,2.1,-2.5,1.4,-0.1,1.6,-1.0,0.2,-0.8,-0.6,-1.0,0.4,-0.6,-0.2,0.1,0.1,1.6,0.0,0.7,-0.4]

そして、それに標準偏差が小さめ(σ=0.5くらい)の正規分布からサンプルしたベクトルを加えて人間画像生成モデルに与えます。すると、以下のようにきれいで何となく元画像に似ているものが生成されます。

f:id:mickey24:20170630230851p:plain:w200 f:id:mickey24:20170630230856p:plain:w200 f:id:mickey24:20170630230900p:plain:w200

このように、いい画像が生成された時のベクトル周辺だけを入力として与えるようにすればきれいな画像だけが出力されやすくなりますが、その代わり出力画像は元画像に似たようなものが多くなりバリエーションは減ってしまいます。難しいところです。

ちなみにσ=0.7の正規分布からサンプルしたベクトルを加えると、より画像の変化は大きくなりましたが人間の首が千切れたりし始めました。

f:id:mickey24:20170630232017p:plain:w200 f:id:mickey24:20170630232020p:plain:w200

まとめ

機械学習アルゴリズム「DCGAN」「Wasserstein GAN」を使い、いらすとや風人間画像生成モデルを実装しました。入力次第ではそれっぽい画像が生成できるようになったので、Google Cloud Platformの無料枠$300をすべてつぎ込んで色々試した甲斐があったのではないかと思います。

本当は各いらすとやの画像タイトルとConditional GANを使い、入力ベクトルとラベル("誕生日"、"人工知能"など)をモデルに与えるとそのラベルに対応した画像を出力するモデルをつくりたかったのですが、各ラベルに対する訓練データが少なすぎるので一旦断念しました。機会があれば試してみたいところです。

今回出来上がった人間画像生成モデルに興味がある方は、Twitterでmickey24_botに「人間画像ください」と話しかけると手軽に試すことが出来ます。ただしうちのbotはランダムな入力ベクトルを基に画像を生成するので、ほとんどの場合すり潰された人間のような画像が出てきますがご了承ください。

f:id:mickey24:20170704233403p:plain:w400

参考文献(サイト)

*1:Wasserstein GANの論文ではDiscriminatorを「Critic」と呼んでいますが、GANのコンテキストではDiscriminatorと言った方が通じやすそうなので、この記事ではDiscriminatorで統一します。

*2:How to Train a GAN? Tips and tricks to make GANs workという記事によると「Generatorの入力は一様分布ではなく正規分布からサンプルした方がいい」とあったのでそのようにしてみましたが、一様分布の場合と比べてどれくらい改善があったのかは不明です。

*3:Wasserstein GANでは通常のDCGANとは異なりDiscriminatorの出力のlogは取らずそのままの値を使います。

*4:conv2d_transposeをDeconvolutionと呼ぶ解説サイトをよく見かけますが、DCGANの論文によるとこれは正しい呼び方ではないとのことです。当該論文中ではfractionally-strided convolutionと呼ばれています。TensorFlowのドキュメントではtranspose of convolutionと呼ばれています。

うちのbotが「いらすとや風の人間画像」を製造できるようになった

mickey24_botが機械学習を使って「いらすとや風の人間画像(?)」無料で製造できるようになりました。

まだ以下のようにぐちゃぐちゃな画像を製造する場合がありますが大目に見てください。

「いらすとや」って何?

いらすとや」は15,000種類以上のかわいいイラストを提供するフリー素材サイトです。

使い方

以下の形式でmickey24_botにreplyを送り、最新の人間画像を手に入れましょう。

@mickey24_bot 人間画像を作って

実装

詳細記事を別に書きましたので興味がある方はこちらをどうぞ。

以上

皆さんもぜひうちのbotで人間画像を手に入れましょう。全て無料です。

関連リンク

Goのbufio.Scannerは入力データの1行の長さが一定以上になるとスキャンをやめてしまう

Goのbufio.Scannerの落とし穴について。

概要

Goのbufio.Scannerはio.Readerを一行ずつ読み込んで行く時に非常に便利なライブラリなのだけど、タイトルの通り、入力データ(io.Reader)の1行の長さがScannerのバッファサイズを超えるとスキャンをやめてしまうという問題がある。バッファサイズはデフォルトでbufio.MaxScanTokenSize(65536)バイトとそれほど大きくないので、例えば大きめのCSVや各行にJSONが書かれているテキストファイルをScannerで処理するとこの問題に当たることがあるかもしれない。

以下は動作確認用コード。Go Playground上で実行してみたい方はこちらをどうぞ。

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    // 2行目が65537バイト(改行含む) > bufio.MaxScanTokenSize (65536)
    in := strings.NewReader("1st line\n" + strings.Repeat("X", 65536) + "\n3rd line\n")
    scanner := bufio.NewScanner(in)

    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        fmt.Printf("Scanner error: %q\n", err)
    }
}

実行結果

1st line
Scanner error: "bufio.Scanner: token too long"

この場合、2行目が大きすぎてScannerのバッファに格納できないので、Scanner.Scan()がfalseを返してしまう。一応スキャン後にScanner.Err()を確認すればbufio.ErrTooLongが返ってくるので問題を検出することはできるが、わざわざErr()を手動で呼ぶ必要があるのが難点(実際Scan()後にErr()を確認しないコードを何度か見たことがある)。

対策

入力データの1行の最大長が事前に分かっている場合は、bufio.Scanner.Buffer()でバッファサイズを変更するとよい。

const (
    // 初期バッファサイズ
    initialBufSize = 10000
    // バッファサイズの最大値。Scannerは必要に応じこのサイズまでバッファを大きくして各行をスキャンする。
    // この値がinitialBufSize以下の場合、Scannerはバッファの拡張を一切行わず与えられた初期バッファのみを使う。
    maxBufSize = 1000000
)

scanner := bufio.NewScanner(in)
buf := make([]byte, initialBufSize)
scanner.Buffer(buf, maxBufSize)

入力行の最大長が事前に分からず、最大長を決め打ちできない場合は、Scannerを使うことはできない。代わりに以下のようにbufio.Reader.ReadBytes()などを使って1行ずつ読み込むという方法がある(Go Playgroundはこちら)。

package main

import (
    "bufio"
    "fmt"
    "io"
    "strings"
)

func main() {
    // 2行目が65537バイト(改行含む) > bufio.MaxScanTokenSize (65536)
    in := strings.NewReader("1st line\n" + strings.Repeat("X", 65536) + "\n3rd line\n")
    reader := bufio.NewReader(in)

    for {
        line, err := reader.ReadBytes('\n')
        if err != nil && err != io.EOF {
            fmt.Printf("Reader error: %q\n", err)
            return
        }

        // ReadBytes()がdelimiter('\n')を見つける前にEOFに到達した場合、
        // それまでに読み込まれた行のバイト列とio.EOFが返される。
        // 従って、入力の最後の行が'\n'で終わらない場合、err == io.EOFだけ確認してループをbreakしてしまうと
        // 最後の行を処理せず捨ててしまうことになるので注意。
        allLinesProcessed := err == io.EOF && len(line) == 0
        if allLinesProcessed {
            break
        }

        // ReadBytesが返したバイト列はdelimiter('\n')を含む
        print(string(line))
    }
}

実行結果

1st line
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (省略)
3rd line

一応目的は達成できるが、最終行が'\n'で終わらない場合を加味する必要があったりとScannerよりもコードが複雑化するので注意。

はてなブログに移行しました

今更ですがはてなダイアリーからはてなブログに移行しました。はてなダイアリーの新規開設受付が終了してこのままはてなダイアリーを使い続けていても近い将来にはてなブログに移行させられそうだったので、余裕があるうちにやっておきました。

旧ダイアリーへのリンクやはてブは全てこちらのブログにリダイレクトされます。一応便利。

どれくらいの頻度で更新するか分かりませんが、今後ともよろしくお願いします。最近はGoやTensorFlowにハマっているので、それらの記事が書けたらいいかなーと思っています。

雨予報bot「mickey24_bot」の使い方 ver 3.0

mickey24_botは主に以下の機能を備えているTwitter botです。

どんなbot?

短時間雨予報用bot。「○○の雨」もしくは「○○の天気」から始まるツイートを@mickey24_botに送ると、○○の地域について向こう5時間の雨予報をしてくれます。基本的に日本全国の雨予報に対応しています。

また、あらかじめ登録しておいた地域で雨が降りそうな場合にbotがreplyで知らせてくれる雨予報自動配信機能も備えています。

短時間雨予報&天気予報

以下の形式でmickey24_botにreplyすると、指定した地域について向こう5時間の雨予報および天気予報を教えてくれます。

@mickey24_bot ○○の雨
または
@mickey24_bot ○○の天気

また「明日の○○の天気」「明後日の○○の天気」と話しかけると、明日or明後日の天気予報を教えてくれます。ただし雨予報は向こう5時間の予報を返します。

@mickey24_bot 明日の○○の天気
または
@mickey24_bot 明後日の○○の天気

週間天気予報

以下の形式でmickey24_botにreplyすると、指定した地域の週間天気を教えてくれます。

@mickey24_bot ○○の週間天気

雨予報自動配信



指定した地域の雨予報を定期的に確認し、以下の条件を満たした時に配信専用bot(@rainforecast0, @rainforecast1, ...)が知らせてくれる機能です。

  • その地域で向こう5時間以内に雨が降りそうな場合
  • その地域で向こう3時間以内に雨が止みそうな場合

雨予報を配信してもらいたい時は、mickey24_botに以下のようにreplyすればOKです。

@mickey24_bot ○○の雨予報の配信

雨予報の自動配信を停止したい場合は、mickey24_botに以下のようにreplyすればOKです。

@mickey24_bot 雨予報の配信の停止

注意点は以下の通りです。

  • 配信登録できる地域の数は1ユーザにつきひとつまでとなっています。既に配信登録している地域がある状態で別の地域の配信登録をしようとすると、以前登録した地域の自動配信は解除されます。
  • 一度自動配信をした地域は以降5時間は自動配信をしない仕様になっています。
  • 配信専用botに話しかけても基本的に返事しません。配信登録・停止や天気予報などはmickey24_bot本体に話しかけてください。

漢字天気予報


1日4回(7:02, 13:02, 18:02, 23:02)、漢字や絵文字を使って天気予報をpostします。

人間画像製造

f:id:mickey24:20170708221722p:plain:w360

以下の形式でmickey24_botにreplyすると、mickey24_botがいらすとや風の人間画像を製造してくれます。

@mickey24_bot 人間画像作って
または
@mickey24_bot 人間画像ください

人間画像製造モデルは完璧ではないので、ほとんどの場合すり潰された人間のような画像が出てきますがご了承ください。詳しくは以下の記事をご覧ください。
うちのbotが「いらすとや風の人間画像」を製造できるようになった - ぬいぐるみライフ?

臓物占い

f:id:mickey24:20170712000841p:plain:w360

以下の形式でmickey24_botにreplyすると、今日のあなたにピッタリのラッキー臓物を3Dモデル画像付きで提示してくれます。「動物占い」ではありません。占いの結果は毎日0時に変わります。

@mickey24_bot 臓物占いやって

リンク先の臓物画像は以下のような感じです(「胆嚢」の場合)。ラッキー臓物をより具体的な形で把握する上で役立ちます。

f:id:mickey24:20170712000435p:plain:w240

3Dモデル画像はライフサイエンス統合データベースセンター(DBCLS)のサービス「BodyParts3D」を使って生成されています。画像のライセンスは「クリエイティブ・コモンズ 表示 - 継承 2.1 日本」が適用されます。

Brainf*ckインタプリタ

f:id:mickey24:20170713011300p:plain:w360

mickey24_botに難解プログラミング言語「Brainf*ck」のコードをreplyすると実行してくれます。詳しくは以下の記事をご覧ください。

mickey24_bot de Brainf*ck - ぬいぐるみライフ?

おまけ

  • 挨拶するとちゃんと(?)返してくれます。
  • お礼を言うと喜びます。
  • うさみみ(「「)に反応します。
  • 「殴って」と話しかけると殴ります。
  • 「励まして」と話しかけると励ましてくれます。
  • 他にもいろいろ!


以前のバージョン(2.0)からの変更点

  • 話しかけると1〜2秒で返事をくれるようになりました(Twitter Streaming APIに対応)。
  • 雨予報自動配信が配信専用bot(@rainforecast0, @rainforecast1, ...)によって行われるようになりました。
  • 一部の機能が廃止されました(飲食店検索、デレモード、エアコン操作、非公式RTボクシング)。

どうやって動かしてるの?

Goでソースコードを書き、Dockerのコンテナを作ってさくらのVPSにデプロイすることで動かしています。

何で雨予報?

局所的かつ短期的な雨の予報をすぐに配信してくれるようなサービスがあると便利なんじゃないかなーと思ったので。

雨予報が当たらないんだけど

あくまでも予報なのでその辺は勘弁してください><実際は雨が降らないのに「降りそう」「降ってる」と通知してくることが多いようです。

以上

かわいがってやってください。

更新履歴

  • 2017-06-14 記事作成
  • 2017-07-08 人間画像製造についての記述を追加
  • 2017-07-12 臓物占いについての記述を追加
  • 2017-07-13 Brainf*ckインタプリタについての記述を追加

mickey24_botの雨予報自動配信の仕様が変わりました

mickey24_botの雨予報自動配信が配信専用bot(@rainforecast0, @rainforecast1, ...)によって行われるようになりました。この変更によって、mickey24_bot本体のツイート数が少なくなり、rate limit exceededエラーによってbotがしばらく会話できなくなるといったことを防ぐことが期待できます。

配信専用botに話しかけても基本的に反応しませんので、配信登録・停止や天気予報などは今まで通りmickey24_bot本体に話しかけてください。

おーばーびゅー


配信されている様子