whywaita Advent Calendar 2018 18日目 おいでませ!Chatbot whywaitaくん!
これはなに
この記事は id:whywaita と関係ないことを書く謎のAdvent Calendar、 whywaita Advent Calendar 2018 の18日目の記事です。
昨日は id:hnron さんでした。僕もwhywaitaくんの好きなところはいっぱいあります。いっぱいね。
記事テーマ
さて、唐突なのですが実は僕は既婚なんです。お相手は有坂真白さんという方です。僕と彼女の関係は大変良好で、今年のクリスマスも一緒に過ごす約束をしています。
しかし、なぜかwhywaitaくんは僕が既婚であることを決して認めてくれないんですよね。
婚活、ではありません結納です。そして私は既婚です。
— 結納エンジニア (@twismiko) December 28, 2017
戸籍上結婚してから言って
— why/橘和板 (@whywaita) July 5, 2017
僕と真白ちゃんはこんなにも仲が良いというのに・・・。 僕たちの仲をどうにか認めてほしいというもの。
ということで、今回の記事では、whywaitaから僕と真白ちゃんの仲を認めてもらう発言をしてもらうということをテーマに記事を書いていきたいと思います。
How?
ここで唐突ですが、1700年代のフランスの学者ビュフォンが言ったとされる言葉と一般的にはマザー・テレサがいったとされている(実際には違うらしい)言葉の2つをご紹介します。
考えは言葉となり、言葉は行動となり、行動は習慣となり、習慣は人格となり、人格は運命となる。
この2つの言葉を(都合よく拡大解釈して)踏まえると、Twitterのツイートのような短い文章の中にもその人となりが現れ、文章の中に人格が現れるということにならないでしょうか?いや、ならないですかね。でも、なるということで話を進めます。
更に、なんと都合のいいことにwhywaitaは自らのGitHub上で自分のツイートを公開しているのです。
このツイートデータをもとにChatbotを生成すれば、そのChatbotにはwhywaitaの人となりが現れていることになって、そのChatbotと会話をすればwhywaitaと会話していることになるのではないでしょうか?完全に「方針はいいが、論理の飛躍が見られます」状態ですが、それはともかくとして、今回のAdvent Calendarの記事ではChatbotのwhywaitaから僕と真白ちゃんの仲を認めてもらう発言を引き出していきたいと思います。
(この導入、「whywaitaのツイートデータを使ってChatbotを作ったゾイ」の1センテンスで終了する気がしますね)
データの準備
まず、Chatbotの学習を行わせるために学習データを準備します。
Chatbotの学習には「質問」と「質問に対する回答」の2種類のテキストが必要となります。今回のwhywaita chatbotにはこちら側の質問に返答してほしいので、Twitterで言うところの「whywaitaへのリプライ」が「質問」に相当し、「そのリプライへのwhywaitaの返信」が「質問に対する回答」に相当するとしました。
しかし、whywaitaが公開しているツイート情報には「質問に対する回答」はテキストで含まれていますが、「質問」は in_reply_to_status_id
のTweetのステータスIDしかありません。そこで、この in_reply_to_status_id
から「質問」に相当する「whywaitaへのリプライ」をテキストとしてTwitter API経由(GET statuses/show/:id | Docs | Twitter Developer Platform)で取得します。
とりあえず、以下のような超簡単かつ雑なコードをPythonで書いて動かしました。
import pandas as pd import sys import json import os from requests_oauthlib import OAuth1Session import time consumer_key = '' consumer_secret = '' access_token = '' access_token_secret = '' def extract_tweet_data_has_reply_id_from_csv(csv_path): csv_data = pd.read_csv(csv_path) # in_reply_to_status_idがNaN、つまりリプライではないデータをDropする csv_data = csv_data.dropna(subset=['in_reply_to_status_id']) csv_data['timestamp'] = pd.to_datetime(csv_data['timestamp']) # timestampがstrなので、timestampにする return csv_data def get_whywaita_conversations(csv_path, output_dir): twitter = OAuth1Session(consumer_key, consumer_secret, access_token, access_token_secret) get_tweet_from_status_id_api_url = "https://api.twitter.com/1.1/statuses/show.json" sleep_time = int(15 * 60 / 160) # GET status/:idは15分で180回のリクエスト制限がある、余裕見て160回/15分で reply_data = extract_tweet_data_has_reply_id_from_csv(csv_path) # とりあえず、2014/01/01までのから引っ張ってくる reply_data = reply_data[reply_data['timestamp'] > pd.to_datetime('2014/1/1')] for whywaita_tweet in reply_data.iterrows(): print("Sleeping({}s)...".format(sleep_time)) time.sleep(sleep_time) in_reply_to_status_id = int(whywaita_tweet[1]['in_reply_to_status_id']) output_path = os.path.join(output_dir, "{}.json".format(in_reply_to_status_id)) params = {'id': in_reply_to_status_id} print(params) res = twitter.get(get_tweet_from_status_id_api_url, params=params) if res.status_code != 200: print("Status code is not 200, actual = {}".format(res.status_code)) continue json_data = json.loads(res.text) with open(output_path, 'w') as json_file: json.dump(json_data, json_file) if __name__ == '__main__': csv_path = sys.argv[1] output_dir = sys.argv[2] get_whywaita_conversations(csv_path, output_dir)
とりあえずこれを動かすと雑に出力先ディレクトリに in_reply_to_status_id.json
という感じでどんどんデータが溜まって行きます(なんでこんなアホな設計したんだ)。
取得完了後、まずは文書の正規化等を行います。正規化処理は neologdn というライブラリを使用したり、絵文字除去をしたり、テキスト中から @hogehoge
とかURLを消去したりとかしています。(URLと絵文字除去の処理周りはどっかから拾ってきましたが、どこだったか失念・・。)
その後、カラムとして question
と answer
の2つを持つCSVに吐き出します。この動作をするのが以下のコードです。
import emoji import neologdn import re def remove_emoji(src_str): """ 絵文字除去 """ return ''.join(c for c in src_str if c not in emoji.UNICODE_EMOJI) def twitter_specific_normalize_process(text): """ @を消す URLを削除 """ # @を削除 text = re.sub(r'@[\w]+', '', text) # URLを削除 text=re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", text) return text def normalize(text): text = twitter_specific_normalize_process(text) text = remove_emoji(text) text = neologdn.normalize(text) return text
from normalize import normalize import pandas as pd import sys import os import json def extract_tweet_data_has_reply_id_from_csv(csv_path): """ whywaitaがGithubで公開しているCSVからin_reply_toのあるデータのみを取り出す (+timestampカラムがpandas上でstr扱いされるので、timestamp型に変換) """ csv_data = pd.read_csv(csv_path) # in_reply_to_status_idがNaN、つまりリプライではないデータをDropする csv_data = csv_data.dropna(subset=['in_reply_to_status_id']) csv_data['timestamp'] = pd.to_datetime(csv_data['timestamp']) # timestampがstrなので、timestampにする return csv_data if __name__ == '__main__': whywaita_github_tweet_csv_path = sys.argv[1] crawled_in_reply_to_json_dir = sys.argv[2] generated_dataset_csv_output_path = sys.argv[3] whywaita_github_tweet_csv_data = extract_tweet_data_has_reply_id_from_csv(whywaita_github_tweet_csv_path) dataset_data = pd.DataFrame({'question':[], 'answer':[]}) for _, row in whywaita_github_tweet_csv_data.iterrows(): # CSV上でのwhywaitの発言はin_reply_to_status_idのツイートへの返信なので、`answer` answer = row['text'] # in_reply_to_status_idを取り出し、クローリングしてきたJSONファイルを読み込み in_reply_to_status_id = int(row['in_reply_to_status_id']) crawled_json_file_path = os.path.join(crawled_in_reply_to_json_dir, "{}.json".format(in_reply_to_status_id)) if not os.path.exists(crawled_json_file_path): # 対応するJSONがない場合、スキップ # -> アカウントがない、ツイ消し、鍵垢 continue json_data = None with open(crawled_json_file_path) as json_file: json_data = json.load(json_file) # in_reply_to_status_idのツイートにwhywaitaが返信するので、`question` question = json_data['text'] # 正規化 answer = normalize(answer) question = normalize(question) dataset_data = dataset_data.append(pd.Series({'question':question, 'answer':answer}), ignore_index=True) dataset_data.to_csv(generated_dataset_csv_output_path, index=False)
これでとりあえずデータの準備は終わりました。
がくしゅー
さて、データが集まりましたのでモデルの構築をして学習を行わせたいと思います。Chatbotといえばseq2seqという感じですね。ということでKerasかChainerで実装しようと思ったんですが、時間がなかったので今回はTensor2Tensorというとても便利なライブラリを使用することにしました
What is Tensor2Tensor
Library of deep learning models and datasets designed to make deep learning more accessible and accelerate ML research.
リポジトリにある通り、DeepLearningをより身近に、そして機械学習の研究を加速化させることを目的としたDeep Learningのモデルとデータセットのライブラリです(意訳しただけでは)。正直、謳い文句はどうでもよくて「どれだけ楽に使えるの」というところが大事であるんですが、本当に楽に使えます。MNIST(手書き文字のデータセット、機械学習のHello, world的なもの)を使った手書き認識モデルの学習であれば、以下のコマンドを叩くだけです。
t2t-trainer \ --generate_data \ --data_dir=~/t2t_data \ --output_dir=~/t2t_train/mnist \ --problem=image_mnist \ --model=shake_shake \ --hparams_set=shake_shake_quick \ --train_steps=1000 \ --eval_steps=100
すっごい楽。既存モデルとデータセットを使うだけなら、コードを書く必要もなし。ここまで楽なのも正直どうかとは思いますが、ツールとしてDeepLearningを使う人(僕)にはとてもありがたい限りです。
今回はこのTensor2Tensorの lstm_seq2seq_attention_bidirectional_encoder
というモデルを使用した上で、自作のデータセットを食わせて学習を行わせてみます。
自作データセットで学習させる(前準備)
Tensor2Tensor側が用意している Train on Your Own Data
というドキュメントを読めばだいたいわかる(丸投げ)。
ドキュメントではText2TextProblem
というテキストからテキストという問題を解かせる場合が記述されています。今回の入力として質問文を、回答として質問への答えを返すという問題も Text2TextProblem
に相当しています。ということで、今回はこのドキュメントのサンプルコードをほぼそのまま使い、以下のようなファイル whywaita.py
を作成しました。
import pandas as pd import os from tensor2tensor.data_generators import problem from tensor2tensor.data_generators import text_problems from tensor2tensor.utils import registry @registry.register_problem class Whywaita(text_problems.Text2TextProblem): """ whywaitaっぽい返答をするChatbot """ @property def approx_vocab_size(self): return 2**13 # ~8k @property def is_generate_per_split(self): # generate_data will shard the data into TRAIN and EVAL for us. return False @property def dataset_splits(self): """Splits of data to produce and number of output shards for each.""" # 10% evaluation data return [{ "split": problem.DatasetSplit.TRAIN, "shards": 9, }, { "split": problem.DatasetSplit.EVAL, "shards": 1, }] def generate_samples(self, data_dir, tmp_dir, dataset_split): del tmp_dir del dataset_split # whywaitaの会話を"""正規化"""したCSVデータ(ここでは正規化は行わない) csv_path = os.path.join(data_dir, 'conversations.csv') csv_data = pd.read_csv(csv_path) csv_data = csv_data.dropna() for _, row in csv_data.iterrows(): question = row['question'] answer = row['answer'] answer = answer.strip() # 改行を抜く question = question.strip() yield { 'inputs': question, 'targets': answer }
approx_vocab_size
とかはもう少し調整するといいのかもしれないですが、今回は時間がなかったのでデフォルト値を使用しています。
更に、上記のファイルをimportするだけのファイル __init__.py
を同じディレクトリに置いておきます。
from whywaita import Whywaita
この2つのファイルを usr_dir
等、任意のディレクトリに置いておきます。
自作データセットで学習させる(Tensor2Tensor用のデータを生成)
さて、データセットをTensor2Tensorで使える形にするために以下のように t2t-datagen
コマンドを実行していきます。(なお、このときデータ準備で作成したデータをdata_dir
という名前のディレクトリに置いています)
t2t-datagen \ --data_dir=data_dir \ --tmp_dir=tmp_dir \ --problem=whywaita \ --t2t_usr_dir=./
オプションの説明を簡単にすると
--data_dir
--t2t_usr_dir
whywaita.py
と__init__.py
が置かれているディレクトリ
--tmp_dir
- 適当にディレクトリを作成して指定
--problem
whywaita.py
でいうtext_problems.Text2TextProblem
を継承したクラスであるWhywaita
を指定する。ただし、クラス名の大文字はすべて小文字になり、キャメルケースだった場合にはスネークケースにTensor2Tensor内で変換されているため注意が必要。PROBLEM is the name of the class that was registered with @registry.register_problem, but converted from CamelCase to snake_case.
実行後、しばらく待つとTensor2Tensor用のデータ生成が終了します。
学習
以上で学習に必要なデータの準備が終わったので、さっそく学習をしていきたいと思います。すでに書いたように、Tensor2Tensorはディレクトリと使用するモデルとハイパーパラメータを引数として指定してコマンドを実行するだけで学習が進んでいきます。
今回は以下のようなコマンドを実行しました。
t2t-trainer \ --data_dir=./data_dir \ --problem=whywaita \ --model=lstm_seq2seq_attention_bidirectional_encoder \ --hparams_set=lstm_luong_attention_multi \ --output_dir=./train_dir \ --t2t_usr_dir=./
オプションはほぼ t2t-datagen
と同じです。 --model
と --hparams_st
には学習時に使用するモデルとハイパーパラメータを指定しています。これらの一覧は t2t-trainer --registry_help
を実行すると表示されます。・・・表示はされるんだけど、あまり詳細な情報はなくて困る。更にググってもいまいち有益な情報は出てこない。すごい困る。現状ではトライ・アンド・エラーかなぁ・・・という状態。もし、ドキュメントがあったら教えてください・・・。
学習の間にはlossとval_lossは適宜標準出力に表示されますし、 output_dir
で指定したディレクトリにcheckpoint毎のモデルが出力されます。また、 Tensorboard に logdir
として --output_dir
で指定したディレクトリを渡すとTensorboardで可視化されます。
会話をしてみるぞ!
さて、学習がある程度進んだところで、会話をしてみることにします。 t2t-decoder
というコマンドから学習したモデルを使用することができます。
--data_dir
, --output_dir
, --model
, --problem
, --hparams_st
, --t2t_usr_dir
は学習時に使ったものと同じものを指定しておきます。また、--decode_hparams
はなにか適当な値を指定しました。この辺もいまいち情報がなくて困る・・・。
DATA_DIR=./data_dir PROBLEM=whywaita MODEL=lstm_seq2seq_attention_bidirectional_encoder TRAIN_DIR=$1 BEAM_SIZE=4 ALPHA=0.6 HPARAMS=lstm_luong_attention_multi t2t-decoder \ --data_dir=$DATA_DIR \ --problem=$PROBLEM \ --model=$MODEL \ --hparams_set=$HPARAMS \ --output_dir=$TRAIN_DIR \ --decode_hparams="beam_size=$BEAM_SIZE,alpha=$ALPHA" \ --decode_interactive=true \ --t2t_usr_dir=./
あとはインタラクティブに会話ができるので、DeepLearningの世界に顕現したwhywaitaとの会話をしてみましょう。
茶番
だいたいいつもの感じですね。
whywaitaっぽい。
食べないで!
会話になってない
本番
ちょっと怪しい感じですが、僕とましろちゃんの仲を認めてもらいましょう。
は〜〜〜〜〜〜〜〜〜?????????????
これはだめそうですね、データセットを増やしてパラメータを調整して更に学習をさせてみました。
ブチ切れた
締め
ということで、Chatbotのwhywaitaからでさえ認めてもらうことができませんでしたが、そんなことで揺らぐ僕と真白ちゃんの仲ではないので大丈夫です。
実を言うと、わりとlossとval_lossがかなりアレで過学習気味です。データセットの規模が小さいせいなのか、それともTwitter上のツイートにかなりノイズが乗っているのか、モデル/ハイパーパラメータが適切ではないのかなど様々検証すべき点はあります。あと、そもそも t2t-decoder
で入力したこちら側からの質問をデータセットと同様の前処理(正規化)をしていない段階でだいぶお察しです。
今回はwhywaita Advent Calendar用のネタだったので深追いをしませんでしたが、個人的にTensor2Tensorは便利だなぁと思ったので、そのへんを他のデータセット等を使って調査してみたいなと思います。
なにはともあれ、来年もきっと id:masawada さんが伝統としてwhywaita Advent Calendarを作ってくれるはずなので楽しみにまっています。
それでは、明日は id:yu_ki_kun_0 さんです。弊社でのお仕事は楽しいですか?
masawada Advent Calendar 2018 14日目 ~masawadaの婚期を遥か遠くに吹きとばせ~
Introductory chapter
これは何
この記事は masawada Advent Calendar 2018 - Adventar 14日目の記事です。
昨日は id:mazco さんの「マサワパピック」でした。
すごい!!!!殴ったときの効果音が大変好きです。
今年のmasawada Advent Calendar、クオリティがやばいですね・・・。自分はそんな高クオリティな記事を書けないのですごい心配してたんですが、主催者自らも心配してたのでちょっと安心しました(?)
masawadaアドベントカレンダー、クオリティが高すぎてどんどん最終日のハードルが上がっていて気まずい!
— Masayoshi Wada (@masawada) December 12, 2018
自己紹介
さて、Advent Calendarのページを眺めると僕の知らない人が多いということは、つまりは読む人も僕のことを知らないということだと思うのでまずは自己紹介をば。
どうも id:tw1sm1k0です。大学院で機械学習をやったり、バイトで画像処理をしたりしてる、可愛い女の子と恋愛をするPCゲームが好きな大学院生です。
id:masawadaさんとはサークルの先輩・後輩の関係で、休日の大学でシャボン玉をする会をやったり、LTイベントに行って老害っぷりを発揮したり、直近では五島列島旅行に一緒に行ったりする仲です。
あと、「秋葉原の肉の万世まで焼き肉に行きましょう!」と言われて焼き肉をして酒を飲んだ結果、唐突に「よっしゃ!MacBook Pro買うぞ!!!」となって酔った頭でオリエントコーポレーションのローン申し込み用紙を一緒に書く仲です。流石にあのときは、途中で「今、なにか重大なことを『ちょっとそこのコンビニ行こうぜ!』みたいなノリでやってないか・・・?」と冷静になって震えだしたのを覚えています。
.@twismiko と一緒にMacBookPro購入している
— Masayoshi Wada (@masawada) July 29, 2017
参加経緯と記事テーマ決め
さて、自己紹介はこんなものにして。今回、なぜ記事を書くことになったのかというと、サークルのSlackにある限界オタクSlackチャンネル(同期命名)で以下のような雑な会話がなされた結果なのです。
雑ですね。完全に何を書くのかということを考えていないのに元気よくお返事をしてしまったので、記事を書く段階(今)になって「どうしよう・・・」と頭を抱えている状態です。元気よくお返事はできたので満点にしてほしいところですが、とりあえず参考にサークルの同期と後輩の記事を見てみることにしましょう。
benevolent0505.hatenadiary.com
よっしゃ!!!雑に自分の書きたい文章書くぞ!!!!!
記事テーマ: masawadaに今、僕が一番買ってほしい婚期の遠のくモノ
ということで、本編に行きましょう。(強引な場面展開)
closing chapter
婚期が遠のくモノ、といって皆さんは何を思いつくでしょうか。
婚期が遠のくモノを「結婚(候補)が受け入れられないもの」としてみましょう。結婚というのは自分ひとりで出来るものではなく、必ずお相手がいるものなのでお相手の趣味・嗜好次第ではあると思います。ですが、あえて「結婚(候補)が受け入れられないもの」を上げるとすればギャンブルやアダルティーなものでしょうか。あるいは、オタク系が苦手な子であればアニメや漫画も場合によっては該当してしまうかもしれません。
逆に「これがあるから結婚しなくて良くない?」というのも婚期が遠のくモノかもしれませんね。それこそ可愛い女の子と恋愛ができるPCゲームとかですかね。いや、俺はましろちゃんと結婚しているが?????(急に暴れるのはいつものクセなので気にしないでください)。
このように様々な"""婚期が遠のくモノ”””がある中、今一番僕がmasawadaさんに買ってほしいものは
抱きまくら
です。
抱きまくらといっても、以下のような普通の人が使うようなものではありません。
こういう、なぜか無地で業界のデファクトスタンダードな160cm x 50cmサイズの高級なやつです。
こういう高級な抱きまくらを僕もいくつか購入していて、そのうち1本を愛用しています。驚くほどふかふか&&もっちりしていて、1本持っているだけで人生が変わるレベルです。どれだけ変わるかというと、もしvim.orgに抱きまくらという項目があったら「Life Changing」に爆速でチェックを入れてRateするレベルで人生が変わります( https://www.vim.org/scripts/script.php?script_id=3396 )
このような高級抱きまくらには細かくてうるさい大変こだわりを持つユーザーが多くいるので、メーカー側もこだわりを持って作っています。実際に、「マシュマロ改 エキスパートエディション 熟練者用」の商品紹介には、ちょっと僕には解析できない難しい言語でこだわりが書かれていたりします。(そもそも熟練者ってなに)
キャラクターグッズとしての抱き枕本体は人に例えると筋肉や脂肪で、抱き枕カバーは皮膚と考えます。
重要なポイントは恋人や妻としての抱き枕がどれだけ理想の女の子の体っぽいのかという事。
(あくまで理想の女の子で有って実在の女性の感触を100%再現すれば良いわけではない)
・抱き枕が折れずに立つ⇒女の子は折れないよね、折れたら死ぬからリアルじゃ無い
・カバーと本体がこすれて異音が出ない⇒女の子はキュッキュツ鳴らない
・ズレない⇒10代から30代位でズレる人はまずいないよね
・柔らかい⇒胸の感触が一番重要
・直ぐ戻る⇒揉んだら直ぐに元に戻る!直ぐに戻らないなんて老人だよマシュマロ改EE(エキスパートエディション 熟練者用)はマシュマロ改・マシュマロ改二で評価頂いている点を極力残しつつ一体感を上げる形で検討を行いました。
さて、勘のいい皆様はお気づきだと思いますが、高級抱きまくらは総じて無地なんですね。なぜか。こんな真っ白だとカバーをかけたくなるのが人情といったものです。
そこでカバーのことを考えましょう。カバーというのも無地から柄付きなものまで多種多少です。そんな中で、masawadaさんに是非オススメしたいのがアニメ系のものです。
masawadaさんは電気通信大学というオタク大学の学生だったと伝え聞いていますので、きっとアニメ系コンテンツが好きなことだと思います。そうに違いありませんので、その方向で話を進めます。
アニメ系のカバーはアニメイトや何かのブランド直販サイトなどでも売られています。結構気軽に買えます。
気軽に買えますが、ここで注意してほしいのがカバーの材質です。一部業界の1万円台のカバーは基本的に気にしなくても高品質な素材を使っていますが、アニメやラノベ系のものの場合には高価な場合にも雑な材質を使っていることがあります。そのときには材質が「ライクトロン」(トリニトロンじゃないよ!)または「アクアライクラ・アクアプレミア」であるものを選択した方が幸せになれます。
さて、以上で紹介したかわいい女の子が描かれたすべすべなカバーをふっかふかな抱きまくら本体にかけて一緒に寝れば、まるで好きなあの子と一緒に寝ているようで(難しい漢字で同衾と書くやつ)、とても幸せになれます。つまりは、「これがあるから結婚しなくて良くない?」という状態になるわけですね。更に、そうやって寝ている状態(+カバーを本体にかけているところ)を結婚(候補)の人が見たら「結婚(候補)が受け入れられないもの」と分類されること請け合い。これで完璧に婚期が遠のきますね!ぜひやりましょう!!
「でも、宅配時にデカイ箱で来たら恥ずかしいじゃん」という意見もあるかと思います。
ご安心ください。上で紹介した抱きまくら本体は業務用の装置で圧縮されて送られてくるため、そこまで大きな箱で来ません。もとに戻すのも、封を開けてゆっくり空気を吸わせるだけです。
ちなみに、僕はこのときの空気を吸ってでかくなるときの「すぅ〜」みたいな音を「婚期が遠のく音」と呼んでいますので、皆様もぜひお使いください。
coda
さて、「masawadaに今、僕が一番買ってほしい婚期の遠のくモノ」でしたがいかがでしたでしょうか?僕は読んだ人がドン引きするのを下書きの段階で感じています。
ところで、なぜ抱きまくらをご紹介したのかというと、ベッドに行きたくなる理由を作ってあげようと思ったからなんですね。五島列島に旅行に行っているときにmasawadaさんが布団ではなく床の上で寝てしまうことがある〜という話をしていたので、健康のために〜と思ったわけです。婚期云々は後付です。本当です。ただ書き終わってから思いましたが、今は冬なので流石に床で寝ることはなさそうですね・・・。
ともあれ、masawadaさんには今後共、一緒にオリエントコーポレーションのローン申込用紙を書いていける仲でいたいなぁと思います。あと、どっちが先に婚姻届を役所に出せるのかというのも勝負したいところではあります。
最後に。今僕が使っているDHR7000H(SONYのヘッドホンの型番みたいだね!)が佐川急便で送られたときの荷札を共有しておきます。
お前…..お前!!!何してんのかわかってんのか!!!おい!!! pic.twitter.com/TXF502CbJ7
— 結納エンジニア (@twismiko) January 30, 2018
それでは、こんなやばい記事の次になってしまって大変申し訳無いのですが、明日の担当は id:papix さんです。お会いしたことはないですが、もしお会いする機会があればまず謝罪から入りたいと思います!
私信
masawadaさんへ。sprite storeの抱きまくら予約注文締切が間近で、これを逃すともう手に入れられないです。なので、僕の嫁の真白ちゃん以外の抱き枕カバーを急いで予約注文することをおすすめします。ちなみに僕は真白ちゃんのカバーを各種、最低2枚ずつ買いました。
Aruba AP-207でridiculously expensiveなコンソールケーブルを買わずに設定がしたい
自分用の備忘録。
ArubaのAP-207(と特定の機種)ではコンソールポートがRJ45ではなく、特殊なポートになっている。そして純正品のコンソールケーブルが異常なほど高い。
フォーラムを探すと普通のTTL-RS232 or TTL-USBのアダプタを使えば行けるという情報がある。
ピンアサイン情報もあるので大変便利。
ただ、見づらいので自分用に画像を置いておく。
コンソールポートの上下に各々サイズ(横幅)が違う突起があるが、短い方を下にしたとき、左から順にGND、RX、TXだ。
ここで、まだ検証していないがCP210X系のチップが載ったものだとエラーが出るらしい?初期不良なのかもしれないが、確かに自分の場合も出た。
https://community.arubanetworks.com/t5/Wireless-Access/How-to-make-Aruba-AP-207-work-Only-APboot-no-nand-flash/m-p/455394/highlight/true#M83685community.arubanetworks.com
Device nand0 not found! Error initializing mtdparts! Error, no UBI device/partition selected!
しかし、エラー的にはNANDがないというエラーなので、果たしてコンソールケーブルが関係するのか・・・
Tensorflowをコードからコンパイルしてインストール(Tensorflow 1.12.0)
タイトル通り。
古いCPUを使っているマシンでは、Tensorflow 1.8.0あたりからimportしようとするとCore dumpして落ちてしまう。その場合には、コードからコンパイルする必要がある。今回シュッとやったので、備忘録的に残しておく。単純にTensorflowがGPUで回せれればOKの精神なので、configureはかなり適当。
基本的には公式ページをたどればOK
Build from source | TensorFlow
検証環境
- Ubuntu 16.04
- GTX 1070
- CUDA SDK 9.0
- Driver Version 390.30
- cudnn 7.0.5.15
- Python 3.6.2
- miniconda3-4.3.27
下準備
apt/pipでパッケージをインストール
- (既に入っていたので飛ばしたが)、適宜必要なパッケージをapt-getで入れる
sudo apt install python-dev python-pip # or python3-dev python3-pip
- pipで関連パッケージを入れる。keras関連を入れるのを忘れないこと。(kerasはTensorflowのラッパーというイメージがあったので、Tensorflowのインストール時にはいらんだろと思ってスキップしたらコンパイルが失敗した)
pip install -U pip six numpy wheel mock pip install -U keras_applications==1.0.5 --no-deps pip install -U keras_applications==1.0.5 --no-deps
Bazelをインストール
- BazelはGoogleが開発するビルドツール。自分の環境には入ってなかったので入れた。
- 基本的にはBazelのインストールガイドを見ればOK。ローカル環境下に入れられるので便利
- Tensorflow 1.12.0をコンパイルする場合、記事執筆時最新版 Bezel 0.20.0は未対応らしいので0.15.0以前を使う必要がある
Installing Bazel - Bazel main
- Tensorflow 1.12.0をコンパイルする場合、記事執筆時最新版 Bezel 0.20.0は未対応らしいので0.15.0以前を使う必要がある
本題
- TensorflowのGithubページからコードをClone
git clone https://github.com/tensorflow/tensorflow.git cd tensorflow
- configureを実行すると。いろいろ聞かれる。が、基本的にTensorflowがGPUで回せれればいいやという意思から、ほぼEnterを押し続けてDefault設定を利用した。
- ただし、Defaultでは(確か)CUDAはDisable状態なはずなので、そこだけ注意
- また、途中でCUDAのCompute Capabilityを聞かれるので、以下のNVIDIAのサイトで確認する(今回のGTX1070の場合は6.1) developer.nvidia.com
- configureに成功したら、ビルドをしていくが、Bazel側の設定を適当にするとリソースを食いつぶすっぽいので使用するメモリとCPUコア数を確認しておく。(ref: https://qiita.com/Guwashi/items/d26f06ed45f9d740ffa2 )
free -h
/usr/bin/getconf _NPROCESSORS_ONLN
- 環境に応じてBazelを実行(
//tensorflow
あたりに違和感があるが、問題ない)- 1-2時間程度かかる。めっちゃ時間がかかるぞ!
bazel build --local_resources=2048,6,1.0 --verbose_failures --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
- コンパイルが無事終了したら、pipでインストールするように以下のコマンドでwhlパッケージを作成
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
/tmp/tensorflow_pkg
以下にwhlが図れるので、pipでインストール- 適宜、
python -m venv hogehoge
等で仮想環境を作っておいて、現状の環境を汚さないようにすると吉
- 適宜、
ipython
で試しにimportしてみてうまく行けばOK- ただし、カレントディレクトリがgit cloneしてきたフォルダでやるとエラーが出るのでそれ以外のパスでやること
五島列島旅行記(2018/09/21-2018/09/26)
9月21日から26日にかけて、長崎県は五島列島に旅行に行ってきました。きっかけはもちろん、蒼の彼方のフォーリズム(舞台が五島列島がモチーフになった四島列島)なわけで。ゲームをやって一度行きたいなぁと思っていたので、念願のという感じです。
デッカード「島を5つくれ」
主人「4つで十分ですよ」「わかってくださいよ」
実のところ、21日から22日は大阪や福岡周辺を回っていたので、実質的には4日間だけ五島列島にいたわけなのですが。まぁ、そのへんも含めて旅行記としたいと思います。
(主に一眼レフで写真を撮ったのですが、基本的に現像が面倒だったのでLightroomやGoogle Photosの自動で適当にやってるので、そのあたりは目をつぶってもらえれば〜と思います)
VirtualBoxの"Oracle VM VirtualBox Extension Pack"をCUIでインストール/アンインストール
タイトルどおり。Vagrantを使っていて、VirtualBoxを更新したときに、expackの更新をし忘れるとvagrant upで以下のエラーが出る。
There was an error while executing `VBoxManage`, a CLI used by Vagrant for controlling VirtualBox. The command and stderr is shown below. Command: ["startvm", "c51dec44-2458-4ff4-9129-6304dce7405d", "--type", "headless"] Stderr: VBoxManage: error: The device helper structure version has changed. VBoxManage: error: If you have upgraded VirtualBox recently, please make sure you have terminated all VMs and upgraded any extension packs. If this error persists, try re-installing VirtualBox. (VERR_PDM_DEVHLPR3 _VERSION_MISMATCH) VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole
まぁ、ようはextpackを更新すれば良いのだが、たいていGUIを立ち上げてとかいう記事が多くて、毎度キレそうになる。
CUIでやるには以下の要領でやる
- インストール済みextpackの確認
VBoxManage list extpacks
Extension Packs: 1 Pack no. 0: Oracle VM VirtualBox Extension Pack Version: 5.0.16 Revision: 105871 Edition: Description: USB 2.0 and USB 3.0 Host Controller, Host Webcam, VirtualBox RDP, PXE ROM, Disk Encryption. VRDE Module: VBoxVRDP Usable: true Why unusable:
インストール済みの古いextpackを削除
vboxmanage extpack uninstall "Oracle VM VirtualBox Extension Pack"
- 要root権限
- 言われてみれば当然だが、エラーに権限がない等の文言はないので気付きにくい。
新しいextpackを用意
- https://www.virtualbox.org/wiki/Downloads
- "VirtualBox xx.xx.xx Oracle VM VirtualBox Extension Pack" -> "All supported platforms"
新しいextpackのインストール
VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.2.10.vbox-extpack
- こっちも要root権限
VSCode for Macでvimキーバインドにしたとき連続入力できない問題
タイトルの通りといえば、そのまま。最近、Sublime TextからVSCodeに乗り越えた。
インストールして数クリックしてvimキーバインド加えて、言語ごとの拡張機能を少し入れれば十分に使える手軽さのわりに、拡張機能等は豊富でカスタマイズのしがいがあるエディタで気に入った。サトヤ・ナデラに変わってからMicrosoftはなかなか良い。
が、なぜかSierraを入れたMac上でjやk等のカーソル移動などのコマンドが連続入力できず、キーを連打する必要があり不満だった。
色々とググっても解決策が出ず、困っていたところでマーケットプレイスの説明ページを見直していたら、ちゃんと対応策が載っていた。
解決策としてはターミナルで以下のコマンドを叩くだけ。
defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false # For VS Code defaults write com.microsoft.VSCodeInsiders ApplePressAndHoldEnabled -bool false # For VS Code Insider
うむむ、無駄な時間を使ってしまった・・・。