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

下町柚子黄昏記 by @yuzutas0

したまち発・ゆずたそ作・個人開発の瓦礫の記録

ひたすら肯定してくれるチャットボットを作ったけど供養します

作りました 供養します UnazukinChan iOS

概要

何を言っても頷いてくれる人工無脳「Unazukin-Chan」(ウナズキンちゃん)を作ったのですが供養します。だいぶ昔の話です。

f:id:yuzutas0:20170320234822p:plain

※注意:この記事は個人的な糞アプリの供養であって、データサイエンティストやAI開発者に向けたものではありません。

もくじ

  1. どんなサービスか
  2. なぜ作ったのか
  3. どうやって作ったのか
  4. なぜ供養するのか
  5. 思ったこと

1. どんなサービスか

  • LINEのようなチャットUIでメッセージを投稿できます。
  • 「なるほど」「すごいな」「悪いのは君じゃない」みたいな感じで励ましてくれます。

iOSのネイティブアプリですが、IPAファイルを知り合いにばらまいただけです。

2. なぜ作ったのか

  1. 誰かに頷いてほしかったからです。
  2. 某所でチャット機能の開発を検討していたのでプロトタイピングがてら作ってみました。
    • 「吹き出し」というUI自体が興味深いと感じました。
    • スマートデバイスの普及に応じて広く親しまれるようになったように思えたからです。
  3. 人工知能ではなく)人工無脳に関心があったので試しに動くものを作ってみたかったからです。
    • 開発時はちょうど第3次AIブームが加熱する手前で、Siriのようにプラットフォーマーにロックするための客寄せパンダが主流でした。
    • より窓口の広いデジタルパートナー(サマーウォーズロックマンEXEみたいな世界)を作ったらカスタマー行動の入口を抑えられるのではという仮説がありました。

3. どうやって作ったのか

以下のサイトで掲載されていたサンプルコードを参考にしました。

[iOS] JSQMessagesViewController でチャットアプリを実装する | Developers.IO

上記の内容をコピーしてペーストして、対話相手が自動返答するように書き換えました。 そんだけ!

- (void)viewDidLoad {
    [super viewDidLoad];
    // チャットUI生成
    [self initNewChat];
    // メッセージデータの配列を初期化
    self.messages = [NSMutableArray array];
    [self makeDictionary];
    // 擬似的に自動でメッセージを受信
    [self startChat];
}

// Sendボタンが押下されたときに呼ばれる
- (void)didPressSendButton:(UIButton *)button
           withMessageText:(NSString *)text
                  senderId:(NSString *)senderId
         senderDisplayName:(NSString *)senderDisplayName
                      date:(NSDate *)date
{
    // 新しいメッセージデータを追加する
    JSQMessage *message = [JSQMessage messageWithSenderId:senderId
                                              displayName:senderDisplayName
                                                     text:text];
    [self.messages addObject:message];
    // メッセージの送信処理を完了する (画面上にメッセージが表示される)
    [self finishSendingMessageAnimated:YES];
    // 擬似的に自動でメッセージを受信
    [self response];
}

// 初回挨拶
- (void)startChat
{
    [NSThread sleepForTimeInterval:1.0];
    self.content = @"やぁ\n何かありましたか?\nよかったら聞かせてください";
    [self receiveAutoMessage];
}

// 肯定
- (void)response
{
    [NSThread sleepForTimeInterval:1.0];
    self.content = self.getDictionary;
    [self receiveAutoMessage];
}

// 辞書作成
-(void)makeDictionary
{
    NSMutableArray *words = [NSMutableArray array];
    [words addObject:@"うんうん"];
    [words addObject:@"わかるわかる"];
    [words addObject:@"わかるよ"];
    [words addObject:@"そっかー"];
    [words addObject:@"そうなんだ"];
    [words addObject:@"なるほど"];
    [words addObject:@"すごいね"];
    [words addObject:@"きみは悪くない"];
    // [words addObject:@"お前がそう思うんならそうなんだろう\nお前ん中ではな"];
    self.terms = words;
}

// 辞書設定
- (NSString *)getDictionary
{
    int n = arc4random() % self.terms.count;
    return [self.terms objectAtIndex:(NSUInteger)n];
}

このときがiOS開発(これを開発とは呼ばないか)デビューだったのでセットアップに手間取りましたが1日で完成しました。

4. なぜ供養するのか

適当な顔アイコンに頷かれても虚しいだけだったからです。

5. 思ったこと

  • UIの重要性!!!
  • 糞アプリは作った直後は面白いですけど、保守する気にならないという問題。
    • 糞アプリだからこそ本気で保守し続けたら、無駄なこだわりがかえって面白いかも、とは一瞬思いました。
    • 辞書を充実させたり、いい感じの応答をできるようにしたり、きちんとした機械学習を挟んだり。
  • また、個人開発でネイティブアプリの保守コストを張るのは辛そうだと思うようになりました。
    • (この程度の規模ならどうとでもなりますが)AppleGoogleの進化に追従しなければいけないので。
    • そこで発想をWEBサービスに絞ってみる→ToCではなくToBの製品が適しているのではと考える→グループウェアに関心を持つようになる→自作Qiita:Teamクローンに繋がります。

yuzutas0.hatenablog.com

でもやっぱり、こうして振り返ると楽しかったです。 面白おかしくやっていきたいですなぁ。

最後に

  • 長くなってしまいましたが最後まで読んでいただき本当にありがとうございます。
  • 一応Githubリポジトリは公開しておきます。最新のXcodeでビルドできるとは思えないですが……。

データ可視化なWEBサービスを作ったけど供養します

作りました 供養します MashBoard Rails

概要

MashBoard(マッシュボード)というサービスを半年ほど動かしていたのですが供養します。

f:id:yuzutas0:20170315214609p:plain

もくじ

  1. どんなサービスか
  2. なぜ作ったのか
  3. どうやって作ったのか
  4. なぜ供養するのか
  5. 思ったこと

1. どんなサービスか

統計データをヒートマップで表示するサービスです。

名前の由来は忘れました。ダッシュボード(DashBoard)と何か(Mではじまる言葉)を掛けていたのは覚えているのですが。

1-1. 対象・用途

かなりニッチで

  • IT勉強会などのイベントが対象
  • どの曜日・時間帯に
  • どのくらい多くのイベントが開催されるか

を描画するだけです。

この時点で廃棄まっしぐらな気がしますね。

1-2. ささやかな機能

フリーワードでの絞り込み!

例えば、"iOS"の分野で絞り込むと「iOSの勉強会はこの曜日のこの時間帯が多い」と分かるので

  • iOS開発チームに対してはその曜日・時間に予定を入れないようにしよう
  • 有志でiOS勉強会を開くときはバッティングしないようにしよう

といったデータドリブンな意思決定ができるようになります。

2. なぜ作ったのか

某所でエンジニア組織の運営に携わることになり、会議体を設計する過程で作りました。

2-1. 経緯

メンバー1人1人にヒアリングしたところ「週次ミーティングが外部の定期勉強会とバッティングするので、時間を早めるか曜日を変えてほしい」なる意見がちらほらと聞こえました。

*その週次ミーティングは、プロダクトや担当領域が異なる複数の開発チームが横断的に情報交換する場で、偉い人のスケジュールに合わせて水曜日の夜に実施していたのです。

メンバーの意見を聞いた私の最初の感想は「勉強会の開催スケジュールが変わったらどうするねん」でした。 バラバラなチームが集まるミーティングなので、スケジュール調整を何度もやり直すのは面倒だからです。

とはいえ、否定から入るのは良くないということで、ひとまずデータを見ることにしました。 また、仮にスケジュールを変更するにしてもビジュアルで示した方が関係者を説得しやすいと考え、可視化ツールを作ることにしました。

2-2. 結果

  • 本当に水曜の夜は勉強会が多かった!(データを見た事実)
  • 某エンジニアいわく「定時帰宅の会社が多いからでは」(定性的な考察)

これらを添えて、「外部勉強会とかぶりやすいスケジュールでミーティングを設定するのはエンジニア組織としていかがなものか」と偉い人に進言。

無事に別の曜日・時間に変更することができました。

めでたしめでたし。

3. どうやって作ったのか

3-1. クローラージョブ

以前作ったものを流用しており、ATND・connpass・DoorKeeper・Zusaarが取得対象となります。

交流会やパーティーを除外するために「勉強会」でフリーワード検索したところ(ミーティングの設計をしていた当時では)4ヶ月分・約540件の有効データを得られました。

yuzutas0.hatenablog.com

3-2. オンラインアプリ

フロントエンドはReactを用いてペラ1の画面を描画しており、バックエンドのRails製WebAPIをコールしています。

ちょうどReactが話題になり始めた時期だったので、お試しがてらチュートリアルのサンプルコードを見ながら実装しました。

  • APIでHashを受け渡す
    • Key:それぞれの曜日・時間
    • Value:イベント開催数が上位何パーセントなのか
  • JSで表組みを描いて、イベント開催数に応じてclassを指定する
  • CSSが各classに応じた着色をすることで、結果としてヒートマップが描ける

4. なぜ供養するのか

Jupyter Notebook があるから
          ↘
         Jupyter Notebook があるから
          ↙
Jupyter Notebook があるから
          ↘
         Jupyter Notebook があるから
          ↙
_人人人人人人人人人人人人人人人_
> Jupyter Notebook があるから <
 ̄^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄

わざわざWebサービスにする必要がない、という一言に尽きます。

データ分析をするだけなら、既存の優秀なツールを活用するのがベストだと思います。 というかJupyter Notebookが強すぎる。

分析結果をもとに何らかのアクションを自動化する、といったプラスアルファがあって初めてWebサービスとして輝くのかなと。 それこそ、会議の自動スケジューリングのような価値提供ができれば魅力的……かも?

5. 思ったこと

5-1. 反省点

説得材料として自分で使ってみて、分かりやすいビジュアルとは言えませんでした。結局は雰囲気でゴリ押しました。いわゆる “Data Visualization” なる分野ですが、単純に面白いです。プレゼン・分析のスキルとしてある程度確立されているはずなので、勘所を抑えられるようになりたいです。

5-2. 良かった点

  • 組織運営の課題を技術で解くことの面白さを感じました。自分の組織だけではなく、世界中の組織の抱える課題を解決できるようになるとビジネス化できるのかなぁとワクワクします。
  • また、フロントエンドの技術検証として、jQueryでやりたきことは十分できるから「最新ツールに振り回されなくても良いのでは説」が私の中で浮上し始めます。

これらの学びが自作Qiita:Teamクローンに繋がります。

yuzutas0.hatenablog.com

最後に

  • 長くなってしまいましたが最後まで読んでいただき本当にありがとうございます。
  • 一応Githubリポジトリは公開しておきます。

IT系勉強会まとめ:Webサービスを作ったけど供養します

作りました 供養します Monomy Rails

概要

Monomy(モノミー)というサービスを半年ほど動かしていたのですが供養します。

f:id:yuzutas0:20170307234328j:plain

もくじ

  1. どんなサービスか
  2. どうやって作ったのか
  3. なぜ作ったのか
  4. なぜ供養するのか
  5. 思ったこと

1. どんなサービスか

1-1. ざっくり説明

勉強会・イベントサイトを横断で検索できるサービスです。

APIを公開している下記4サイトが対象となります。

  • ATND
  • connpass
  • DoorKeeper
  • Zusaar

1-2. 画面イメージ

  • 検索画面
  • カード型の一覧表示画面

f:id:yuzutas0:20170307234328j:plain

  • 詳細画面
  • サイドバーにて類似レコメンド

f:id:yuzutas0:20170307234348j:plain

  • メモ代わりのメール送信

f:id:yuzutas0:20170307234409j:plain

1-3. 由来・コンセプト

名前の由来は「物見遊山」(ものみゆさん)です。和風シリーズ。

移動に制限のあった江戸時代の人は、お参りに行くという名目で、外の世界を旅行したそうです。 同じように、勉強会・イベントでは、スキルアップだけでなく、視野を広げたり、新しい人と出会う楽しみもあります。 そういう前向きな気持ちで一歩踏み出せるような意味を持たせる名前にしました。

このようなコンセプトで作ったサービスとなります。 実際にいくつか勉強会を主催・参加してみて、もっと自分の世界を広げたいなぁと思いました。

2. どうやって作ったのか

過去の個人開発サービスと同じような流れなので細部は省略します。

yuzutas0.hatenablog.com

2-1. システム構成

構成図・技術要素は以下の通りです。

f:id:yuzutas0:20170307234556j:plain

  • APFW:Rails
  • DB:MySQL
  • 検索エンジン:Elasticsearch (provided by Compose)
  • メール配信:SendGrid
  • HW/NW/OS/MW:CloudFoundry (wrapped by Bluemix)

2-2. クローラージョブ

f:id:yuzutas0:20170307234617j:plain

WorkloadSchedulerにてcron相当の設定を行い、Railsバッチ処理を叩きます。 実際にはHTTPリクエスト経由となるのでRails側でAPIを用意しました。

Railsバッチからは各勉強会サイトのAPIをコールしてDB・検索エンジンに保存します。 APIコールで時系列を指定し、過去に同じページを保存していればクローリングを打ち切ります。

2-3. オンラインアプリ

f:id:yuzutas0:20170307234631j:plain

エンジニアがIT勉強会を探すためにサイトを訪問するとRailsレンダリング結果を返します。 Bluemix標準ランタイムだと最新バージョンに対応しないため、CloudFoundryの情報を漁ってカスタム設定にしました。

フリーワード検索と類似文書レコメンドではElasticsearch、それ以外ではMySQLからイベントを探します。 類似文書レコメンドは「More Like This」でお手軽実装となっています。 また、メール送信の要求を受けたらSendGridに送信リクエストを送ります。

2-4. その他開発環境

f:id:yuzutas0:20170307234647j:plain

せっかくのBluemixなのでサービス開発に使えそうなものをいくつか試しました。

  • Auto-Scaling
  • キャパシティ計測ダッシュボード
  • Todo管理
  • 脆弱性診断ツール
    • クローリングしたHTML・画像をそのまま出力している点を指摘されました!

2. なぜ作ったのか

2-1. PaaSの検証のため

サーバ構築・メンテナンスの手間を省くためにPaaSを使えないか検証したかったからです。 インフラ観点だけでなくアプリ観点で使い勝手を検証するためにサンプルアプリとして作成しました。

2-2. UIの学習のため

HileSearchというWEBサービスGigazineに掲載いただいた際、使い勝手の悪さをあちこちでご指摘いただきました。

yuzutas0.hatenablog.com

そこで、検索>一覧>詳細>アクション、という一般的なToC向けサイトの構成を学びたいと考えました。 自分で1度作ったあとに、世のサービスを見ると「こういう工夫が必要だったのか!」と気付けるだろう、という作戦です。

f:id:yuzutas0:20170307234429j:plain

ここでの学びが後述のQiita:Teamクローンに繋がります。

2-3. フィードバックサイクルのため

磨き込み・学習のためには、継続的にユーザーからのフィードバックを得ることが重要だと考えました。 IT勉強会というテーマを選んだのはそのためです。

  1. IT勉強会のためのサイトを作ったよ!という発表をする
  2. 勉強会に参加する人は「勉強会」自体にもある程度関心がある(はず) → 意見を出してもらえる(はず)
  3. 意見をもとに改修 → その旨を次の勉強会で発表する → 2に戻る

こういった正のサイクルを回しやすいのではないかと、という仮説です。

2-4. 本音

というのは半分言い訳で、実際には色々な勉強会に顔を出して、色々な人と話をしてみたかった! そのために話す題材が欲しかった!できたら一緒に盛り上がりたかった!それだけです!

4. なぜ供養するのか

4-1. 機能

勉強会でフィードバックを得るためには1つ目玉機能が欲しいと考えました。

  • Tinderのように好き嫌いを回答して機械学習してくれたら面白いやん!
  • だとしたらWebよりもiOS/Androidネイティブアプリの方が良いのではないか!

ここで機械学習スキルの壁に当たり、迷走もとい勉強することになります。

yuzutas0.hatenablog.com

4-2. 保守

Courseraを終えて見積もり・実装ができるようになると別の課題に思い至りました。 Web/iOS/Android/レコメンドと、システムを広げてしまうと、そのあとの保守が辛くなります。 ToB向けサービスで、Webに絞った方が磨き込みが容易ではないか、と考え始めるようになりました。

4-3. 頻度・速度

加えて、勉強会よりも業務の中でドッグフードできるグループウェアに魅力を覚えるようになります。 というのも、同僚からフィードバックを得るほうが圧倒的に学習の頻度が多いだろうと考えたからです。

この考えがQiita:Teamクローンの開発につながります。

yuzutas0.hatenablog.com

5. 思ったこと

供養する理由を文字に書き出した感想。

「まだ供養しなくてよいのでは?」

やる前から否定してばかりで格好悪い。

  • iOS,Android,レコメンドは実装してしまおう。
  • 保守が大変なら周囲を巻き込もう。協力したくなるような絵を描こう。
  • 勉強会に参加してフィードバックを貰おう。

というわけで、そのうち再開するかもです。 アイデアは捨てるより実現する方が楽しいよね。

ここまで書いてブログ投稿を取りやめようか迷いましたが、せっかくなので投稿します。

最後に

  • 長くなってしまいましたが最後まで読んでいただき本当にありがとうございます。
  • 一応Githubリポジトリは公開しておきます。いつかまたpushする日が来るかなぁ。

WEBサービスを作りました(人生でやりたい100のリスト)

作りました My100Tales Rails

概要

My100Tales(マイ・ハンドレッド・テイルズ)というサービスをリリースしました。

f:id:yuzutas0:20170301194905p:plain

もくじ

  1. どんなサービスか
  2. どうやって使うのか
  3. なぜ作ったのか
  4. どうやって作ったのか
  5. 思ったこと

1. どんなサービスか

  • 人生でやりたい100のリストを書き込み、育て、実現するためのサービスです。
  • 機能・UIの実態としてはお一人様向けのQiita:Teamクローンとなります。
  • 名前の由来・コンセプトは以下の通りです。和風シリーズです。

サービス名は「私だけの百物語」という意味です。

百物語では、百の怪談を語り終えて、最後の蝋燭の火を消したとき、本当に怪奇現象が起きると言われています。 また、"tale"は「怪談」だけでなく「夢物語」「おとぎ話」の意味を掛けています。

このサービスは利用者が自分だけの「夢物語」を書き出す場所です。 やりたいことを百個書き出す頃には、きっと何か1つは実現しているのではないでしょうか。

2. どうやって使うのか

マークダウンエディタで投稿したり

f:id:yuzutas0:20170301195228j:plain

投稿内容を読み返したり

f:id:yuzutas0:20170301195248j:plain

一覧から投稿を探したり

f:id:yuzutas0:20170301195307j:plain

キーワードやタグで絞り込んだり、スコアで優先順位付けたり、検索条件を保存したり

f:id:yuzutas0:20170301195323j:plain

追記コメントを添えたり

f:id:yuzutas0:20170301195336j:plain

バックアップファイルを出力したり

f:id:yuzutas0:20170301195349j:plain

そんな感じです。

3. なぜ作ったのか

  • プロトタイプとして
    • グループウェアの企画・開発に関心があったので、そのプロトタイプがてら実際に使えるものを作ってみました。
  • 管理ツールとして
    • 自分自身がアイデアの管理ツールを必要としたからです。
    • 1日1つ新規事業のアイデアをメモに書き続けたところ、アイデアが数百を超えてしまい、ツールが必要になりました。
    • 某開発チームにて、案件管理にQiita:TeamとGoogleSpreadSheetを併用しているのを見て、両方の特性を兼ね備えたツールが欲しいと考えました。
      • そこでは、SpreadSheetは案件リストを管理するために使っていました。列の追加・絞り込み・ソート機能を活用し「工数は小さく、効果見立ては大きい」といった条件で優先度を判断していました。
      • 一方、Qiita:Teamは個々の案件の要件を管理するために使っていました。気軽に更新できるのが魅力です。案件リストのURLリンクから各案件詳細に遷移していました。
      • また、別のチームでは、JIRAとConfluenceの組み合わせで同様の使い方を試みています。

4. どうやって作ったのか

基本的には過去のサービス開発と同じ流れです。

yuzutas0.hatenablog.com

yuzutas0.hatenablog.com

4-1. 概要

4-1-1. 以下の手順を踏みました(後述)

  • 企画:ペルソナ、課題、解決策
  • 開発:要件、設計、実装、テスト
  • リリース:環境構築・スクリプト整備、バグ修正

4-1-2. システム構成は以下の通りです

4-1-3. その他の開発ツールは以下の通りです

ちなみに、トップの背景写真は、夜灯(よとぼし)というお祭りにて、子供たちが手作りした和紙灯籠を撮影したものです。 サイトカラー・用途に合うように色味・明るさ・ぼかしといった加工をしています。

4-2. プロセス

4-2-1. 企画

どちらかというと自分向けの側面が強いので、軽く想定を置いただけです。

  • 分析を突き詰めるようなことはしていません。
  • 事前検証として、周囲にインタビューをしたり、ダミースクショで反応を見たりはしました。

4-2-1-1. ペルソナ

どんな利用者を想定しているか。

  • 属性としては広告・ソフトウェア系企業に勤務する20代半ば〜30代前半の若手会社員を想定。
  • プライベートではEvernoteなどのツールにアイデアを書き込んでいる。
  • 業務ではQiita:TeamやConfluenceといったグループウェアを活用している。
  • 仕事を終える時間が遅いので、プライベート向けツールよりも、業務ツールに接する時間のほうが長い。
  • 少しずつアイデアを育て、優先順位を付けることで、やりたいことを1つ1つ実行していきたいと考えている。

4-2-1-2. 課題

どんな痛みを抱えているのか。

  • グループウェアのUI・機能で情報を整理することに慣れてしまっている。
  • プライベートでのメモツールでの情報管理に違和感を覚えている。
  • 1つのツールで一覧管理・詳細メモの両方を満たしたいと考えている。

4-2-1-3. 解決策

なぜ既存の製品では駄目なのか。

  • グループウェアを1人で利用しているブログ記事を読むと魅力的に思える(ので既存の製品は駄目ではない)。
  • ただ、30日間無料のあとにお金を払って使い続ける自分を想像できずに二の足を踏んでいる。
    • 特にバックアップ機能が明記されていないときの尻込みたるや!
  • 各種グループウェアは検索→一覧→詳細の画面導線が十分に磨き込まれているとは言い難いのでツール併用が必要。
    • 案件管理ツールとして使うこと自体が間違い、という使い手側の問題もありますが。
    • とはいえ、検索機能の強化をPRする新興グループウェアがいくつかあるのも事実かなと。

※偉そうに書いていますが、自分でサービスを作った後に、改めて既存サービスを見返すと、いかに洗練されているかがよく分かります。

4-2-2. 開発

4-2-2-1. 要件定義

最初に、機能要件を洗い出し。

  • ユースケースをもとに「必須の要件」と「あると嬉しい要件」を整理しながら列挙しました。
  • 例えば、個人サービスは基本的に信用できないものです。少しでも安心できるよう、利用者がバックアップを保存できる機能は必須です。
  • また、外出中や就寝時にもアイデアは浮かびます。どこでも書き留められるように、スマートフォンから気軽に投稿・追記できるようにしました。

次に、画面要件を作成。

  • 検索→一覧→詳細の画面導線については、類似構成のサイトを参考にしました。
    • 特に参考にしたのがHOME'SとSUUMOです。たまたま利用していたこともあり。
    • 投稿の「探しやすさ」という観点では、ToB向けのグループウェアよりも、ToC向けのWEBサイトの方が、機能・UIともに磨き込まれているように思います。
  • カラースキーマについては、白をベースにして、一部アレンジカラーを加えることにしました。
    • 各種グループウェアが白ベースでデザインされているためです。
    • グループウェアに慣れている人が使うので、インターフェースは似通ったものが望ましいとの意図です。

そのあとは、データ要件。

  • 基本的にはRailsのシンプルな生成に任せる形としました。
  • 必要な項目を素直に正規化してER仕様を策定しました。

非機能要件は簡易なポリシー・ルールのみ策定。

  • セキュリティ:個人サービスとして無理のない範囲で対策する。
  • レスポンスタイム:開発時にパフォーマンスを測定してすぐ直せそうなら直す。
  • キャパシティ:各種リソース使用量は40%を許容上限とする。
  • インフラ:これまでの個人サービスと同様に最小構成のVPS1台とする。

詰め込みすぎると永遠に終わらないので、無理のない範囲でゆるく定義しました。

4-2-2-2. システム設計

モジュール構成は以下の通りです。

f:id:yuzutas0:20170301202844p:plain

作図にはPlantUMLを利用しています。テキストでバージョン管理できるのが嬉しい。

4-2-2-2-1. フロントエンド

技術要素

  • 再掲: Sass(libsass), CoffeeScript + jQuery + Vue.js
  • いくつか最近のフレームワークやライブラリを軽く触ってみました。
  • 趣味開発ならSassとjQuery(せいぜいVue.js)で十分だという結論に至りました。

構成

  • HTML(ERB)は、各DOMを一意にできるよう、BEMライクなclass/idを指定しています。
  • CSS/JSともに「DOMと一対一で対応する層」から「共通ロジックを扱う層」を呼び出す2層構造としています(下図参照)。
  • 最初から細かく分け過ぎるようなことはせず、必要に応じて後から分割を検討できる程度に留めています。

f:id:yuzutas0:20170301205858p:plain

こちらは某所のLT向けにyuml.meを使ったので資料を流用しています。

4-2-2-2-1-1. CSS

f:id:yuzutas0:20170301210200p:plain

SMACSSライクな構成としています。

  • Base:フォントサイズのように横断で利用する変数の設定など。
  • Module:共通部品(例:ボタン)を定義する。
  • Layout:
    • .erbファイルと対応する形で.css.sassファイルを作成する。
    • 一意となる.classに対応する形でスタイルを指定する。

なお、Bootstrap拡張ライブラリであるHonokaを利用していますが、HTMLから直接クラス名を指定するのではなく、上記ルールに寄せています。

こうではなく

<div class="btn btn-primary">ボタンだよ</div>

こうします。

<div class="module__button">ボタンだよ</div>
.module__button {
  @extend .btn;
  @extend .btn-primary;
}

ボタンのデザインを変更したいときはmoduleファイルを変更するだけで済みます。HTML上に散らばる.btn .btn-primaryを全て書き換える必要はありません。

また、「HTMLは文書構造」「CSSはスタイル」と責務を明確に分離することで、「色を変えたいときには、クラス名ではなくCSSをいじる」と保守判断できるようになります。

# 4-2-2-2-1-2. JS

f:id:yuzutas0:20170301210258p:plain

CSSと同様に二層構造(+α)としています。

  • Main:
    • .erbと同じ単位で.coffeeを作成する。
    • 一意となる#idに対応する形でスクリプトを実行する。
  • Util:
    • Mainから呼ばれるロジックを定義する(例:モーダルの生成やタブの切り替え)。
    • 任意のDOMに対して処理を実行する。
  • Template:動的なHTMLレンダリングで用いるテンプレートを切り出したもの。

なお、Vue.jsはデータバインディングにのみ利用しています。

@previewMarkdown = (editorDom, previewDom, vueDom) ->
  new Vue(
    el: vueDom
    data:
      content: $(editorDom).val()
    filters:
      preview: (content) ->
        markdownToHtml(content)
  )
4-2-2-2-2. バックエンド

趣味開発・スモールスタートのデファクトスタンダードという認識のもとでRailsを採択しました。 大体のことは無難に実現できるので十分かなと思っています。

最初はデフォルトのMVCで実装を開始しましたが、最終的には以下の形になりました。

f:id:yuzutas0:20170301210457p:plain

  • View:HTMLテンプレート。
  • Controller:リクエスト・レスポンスの窓口。
    • Decorator:画面出力のための整形処理。ControlleからViewへの受け渡しで利用。
    • Helper:画面出力のための整形処理。Viewから呼び出して利用。
    • Handler:例外処理を担うInterceptor。
  • Service:Controllerからコールされる業務ロジック。
    • Factory:レコードのCreate処理をModelに指示する。
    • Repository:レコードのRead,Update,Delete処理をModelに指示する。
  • Model:ER構成と密結合なEntity。永続化層とのやり取りを担うDAO。
    • Finder:検索処理。Elasticsearchとの繋ぎこみ。
    • Searchable:検索設定。Elasticsearchとの繋ぎこみ。
  • Form:検索や投稿のフォーム。ERと連動せず、横断して使うDTO

デグレが頻発したタイミングが2度あり、その度にクラスを分割する形で再設計しました。 なお、命名は便宜上のもので、正式な用語通りの意味・実装ではありません。

4-2-2-3. 実装

コツコツとコーディング。以下の点を意識しました。

  • なるべくライブラリを使って自前実装はシンプルに抑えました。そのためのRailsjQueryです。
  • 静的解析(Rubocop, Rails Best Practice)を用いて、なるべく綺麗にするように心掛けました。
    • 特に考えず初期設定で検査→可能な範囲で通せるようにリファクタリング
    • 守るのが難しい箇所はルール違反を許容。例えば、メソッドをXX行以内に抑えましょう!といったルールです。
  • 『パーフェクトRuby』を毎日コツコツと読み、「こう書けば良かったのか!」の気付きがあれば都度コードを修正しました。
  • ActiveRecordが向かない箇所は生SQLに寄せました。
    • 具体的には、無駄なクエリが発生する箇所、Arelを使わざるを得ない箇所です。
    • トリガーとしては、BulletでN+1が出たとき、動作確認で挙動が遅いと感じたとき、クエリの実行ログを見て違和感を覚えたときです。
# get hash about tag's name and how many tales the tag is attached to
# => { name: size, ... }
# => e.g. { 'testOne': 21, 'test2': 15, 'test_three': 23 }
def self.name_and_attached_count(user_id)
  # query
  query = <<-'SQL'.freeze
    SELECT
      T.name,
      COUNT(R.id)
    FROM
      tags T
    LEFT OUTER JOIN -- count for zero attached record
      tale_tag_relationships R
    ON
      T.id = R.tag_id
    WHERE
      T.user_id = ?
    GROUP BY
      T.id
  SQL

  # execute
  CommonRepository.select_hash_with_user_id(user_id, query)
end

4-2-2-4. テスト

最小工数で最低限の品質を担保するために、探索的テストのみ実施しました。

探索的テストとは

  • 最初に確認観点のみを洗い出して、手動でアプリケーションをいじります。
  • 途中で「あれ、この場合ってどうなるんだっけ」と疑問が出てきたら、その挙動を試します。
  • このときにバグが見つかることが最も多いという研究があるそうです。
  • その気付きを期待したテストだそうです。

※ただし実施者のスキル・経験に依存するとのこと。そりゃそうだ。

自動テストは書いていないです。以下、言い訳。

  • 仕様がコロコロ変わるので保守しきれる自身がなかったためです。
  • デグレが発生したら設計で担保する形にしました。「なぜデグレが起きるか=実装時に影響範囲がわかりにくいから」という考え方です。

うーん。苦しい。

4-2-3. リリース

4-2-3-1. 環境構築

いつも作業手順メモが読み返し辛いので、今回は .sh ファイルに書き込みながら実施しています。 ポート番号やパスワードは環境変数として隠蔽・別管理としました。

4-2-3-2. デプロイ

本番環境でのバグ検知→修正反映のリードタイムを短縮するため、コマンド1つで再リリースできるように準備しました。

  • Capistranoスクリプトを作成。
  • ビルドジョブをチューニング。
    • timeout対策:ローカルで assets precompile するように修正。
    • コンパイル時間短縮:Sassからlibsassに変更。

4-2-3-3. テスト利用

友人や同僚にお試し利用を依頼しました。事前に作成途中のものをPRしたり、デモ会を開いたりと涙ぐましい努力をしました。 その際に指摘いただいた不具合、誤表記、機能不備は修正しています。

引き続きご指摘は絶賛募集中なのでお気軽にお声がけください。

5. 思ったこと

5-1. Keep

良かったこと。

  • 人に使ってもらうための基準を決めたこと
    • 特にバックアップ機能。個人サービスなので、バックアップできないと胸を張れないと判断しました。
    • 他には利用規約・プライバシーポリシーの明記。ほとんどテンプレートの転用ですが、それでもサービスとして最低限必要だろうと。
  • 過去の反省点を踏まえて改善していること
    • クラス分割、静的解析、クエリ改善、デプロイ自動化など、個人開発でサボりがちな部分を実施したのは良かったです。
    • トップページにスクリーンショットを添えたり、安心してもらうための文言を添えたり。
    • 念願のモバイル対応です。過去に作った非対応サイトは直したいなぁ。
  • やり抜いたこと(1番大事)
    • やりたいことや直したい点は山ほどあるのですが、永遠に終わらないので泣く泣くスコープアウトしました。
    • 色々とアイデアはあるわけですが、何事も実現してこそですからね。

5-2. Problem

反省点は多々あります。

5-2-1. プロダクト

やりたいことだらけです。

  • 登録後の最初のアクションを促すガイダンスが欲しい。
  • 各種機能を解説するページが欲しい(特にスコア機能の分かりにくさ)。
  • 検索条件の履歴がクエリなので分かりにくい(自然言語に翻訳したい)。
  • 絵文字・テーブル補助・タスクリストなどマークダウンにあってほしい機能がない。
  • テンプレート機能が欲しい。
  • カラーテーマを入れ替えたい(黒ベースを選べるようにしたい)。
    • 目に優しいから。
    • プライバシーフィルター利用時に背景が黒だと他の人にいっそう見えにくくなるから。
    • エンジニアは黒い画面の方が慣れているであろうから。
    • 夏の夜が当初のコンセプトイメージだったから。

5-2-2. システム

直したい点だらけです。

  • deprecatedなツールを利用したり(例:bower)、最新バージョンに追従できていなかったり(例:Railsのバージョン)、個人開発とは思えない体たらく。
  • 投稿内容が増えれば増えるほど負荷が過度に上がる仕様になっているので直したいです。特にモーダルの表示ロジック。スケーラブルではありません。
  • ElasticsearchやRedisをもっと活用したいです。特に検索処理はフリーワード機能だけでなく全般的にElasticsearchに寄せたい。
  • Controller -> View にインスタンス変数を大量に受け渡しているので、Value Objectのような層を設けたいです。
  • 再現・計測できていないのですが、やたら処理が重いという声があるので、チューニングした方が良さそうです。
  • サーバセットアップの完全自動化。せめてローカルで使いたい人はコマンド1つで立てられるようにしたいです。
  • やはりテストコードは書きたい。色々と言い訳はしましたが。

5-2-3. プロセス

作りたいものの割に時間を掛けすぎました。

  • 実稼働は約1人月程度ですが、工期は1年弱です。さすがに趣味開発にしては長すぎたように思います。
  • いろんな工夫ができたはず。サーバセットアップをせずにPaaSを使えたのでは、KVSや検索エンジンを使わなくても良かったのでは。
  • 回り道を楽しむのも一興ではあるけど、最短ルートを走る努力も必要だと反省しています。
  • プロダクトオーナーの1番の仕事は「やらないこと」を決めることだと言いますし。

また、個人開発のブログではあるのですが、1人での活動に限界を覚え始めています。

  • 仕事が炎上してもプライベートプロジェクトを「常に誰かが進歩させる」状態になっていると心強いなぁと思いました。
  • 人に見せて「こうしたら面白そう」と盛り上がった場面があって、一緒に形にできたら楽しいだろうなぁと思いました。

チームや組織の重要性・可能性を強く感じています。

5-3. Try もとい 感想まとめ

  • 良い点も改善点も試したい点も山ほどありますが、何よりもやっぱり、自分のアイデアを形にするのは本当に楽しいです。
  • もっともっと楽しめるような、そして可能なら周りを楽しませられるような、そんな企画を100個でも1000個でも実現していきたいなぁと改めて思いました。

最後に

  • 長くなってしまいましたが最後まで読んでいただき本当にありがとうございます。
  • 改善点やご意見など、何かあればコメント欄やGithubTwitterでご指摘いただけると嬉しいです。
  • 指摘された点や自分で使ってみて気になった点はIsuueに挙げていこうと思います。

ニコニコ学会データ研究会に参加しました&モザイク画生成スクリプトを作りました

参加しました ニコニコ 数学 作りました

ニコニコ学会データ研究会というイベントに招待いただき、セッション3「数学」で発表を行いました。

f:id:yuzutas0:20160330215626j:plain

どんなイベントか

Peatixのイベント紹介ページによると

データ研究会は「データ分析を始めたい人」「データ分析を仕事にしている人」「面白い発表が好きな人」などなど、誰でも参加できる気軽な研究会です。 ...... (中略) ...... データで面白ければ節操のない研究会です。最近は夏コミで薄い本「ニコ知能」も上梓し、データおもしろがり分野のエッジをひた走っています。

とのことです。

他の参加者のブログ・スライド

多種多様な方々が登壇して、普段なかなか接する機会のない魅力的な話を聴けました。

参加のいきさつ

  • 昨夏にはニコニコ学会、昨秋には日曜数学会(=趣味で数学をする人たちの集まり)、それぞれのイベントに参加しました。そこでのご縁からお声掛けいただきました。
  • 100人以上のデータサイエンティストの前で立派な話をする自信はありませんでしたが、せっかくなので恥をかいて勉強しよう!という気概で参加しました。

yuzutas0.hatenablog.com

yuzutas0.hatenablog.com

どんな話をしてきたか

こちらが当日の発表資料になります。

苦労話

当日は時間の都合で省略しましたが、実装上の苦労について、この場で振り返りたいと思います。

画像サイズ

特に1番苦労したのは画像のサイズです。 最終的に完成したモザイク画は160MBにもなってしまいました。

サイズが大きくなった理由

  • 今回使った対象画像(target_image)のサイズは 200 pixel x 200 pixel です。
    • いくつかサイズを試してみて、これが荒すぎないギリギリでした。
    • これより小さいと最終出力がただのモザイクになってしまいます。
  • 同様に、要素画像群(element_images)は 100 pixel x 100 pixel です。
    • モザイク画を拡大したときに1つ1つの画像が潰れないギリギリでした。
    • 個々の画像が判別できないと、プレゼンの魅力が半減します。
  • 上記を組み合わせると 20,000 pixel x 20,000 pixel となります。
    • ラップトップで1人で楽しむなら縮小余地があるのですが、大画面での発表を想定するとこれが最小サイズとなりました。
    • まぁ結局スライドに収まらなくて 1/3 に縮小したんですけどね!!!最初から 1/3 スケールで処理すれば良かったよ!!!

サイズが大きくなったことによる影響

  • ソースコード上にjpgとpngが混在している
    • 最初はjpg拡張子のみを使うつもりでした
    • 160MBになるとjpg拡張子の限界を超えるのですね
    • 結果として割れ窓理論でコードベースの汚さが加速しました
  • モザイク画を自慢したいのにSNSにアップできない
    • 泣く泣く小サイズ版をTwitterにアップしました!が!拡大しても潰れています!
    • png拡張子の画像ファイルはzipにしても圧縮効果がないのですね
  • とにかく処理が大変
    • 目視しながらトリミングしようと思ってもFireworksが落ちます
    • メモリの読み込みや解放を工夫しないとRubyが落ちます

Ruby

スクリプト開発で利用したライブラリについて。

RMagick (Problem)

画像処理に利用した RMagick のリファレンスが分かりにくかったです。

  • 後で Ruby Style Guide(和訳)を読んで知ったのですが、今は RMagick は非推奨で、代わりに MiniMagick を使った方が良いそうです。そういえば、Rails Tutorial(和訳) にも同じことが書いてあったような。
  • どのライブラリがデファクトスタンダードなのか把握しておけば、もっと効率的に開発できるのだと反省しました。
  • ちなみに、 OpenCV であれば Python が公式でサポートされている、とのことでした。機械学習や画像処理は Python に任せた方が良いのかな。

Rubocop (Keep)

コーディング規約を Rubocop で遵守しました。規約違反を指摘するだけでなく、ある程度は自動でフォーマッターを掛けてくれます。最高。

  • 過去に作ったWebサービスを手直しできていない理由の1つに、コードの保守性が低い、というのがありました(エンタープライズな大規模アプリケーションの技術的負債に比べれば可愛いものですが)。
  • ついつい甘えがちな個人開発において、規約を確実に遵守するには、自動化するしかありません。ということで Rubocop を導入して、 .rubocop_todo.yml に反映される指摘事項が常にゼロとなるように心掛けました。
  • チーム開発でも同じで、静的解析で十分なはずの指摘に、わざわざ人間が時間を費やすのは勿体ないように思います。その分を他のことに費やした方が生産性が高まるのではないかと。
  • まぁ、結局汚くなっちゃったんですけどね!!!

質疑応答

長丁場で集中力を欠いていたこともあり、かなり雑な回答ばかりしてしまいました。 非常に申し訳なかったなぁと反省しています。

終了後に感想・質問を書いた付箋を何枚かいただいたので、リベンジも兼ねて回答します。

画像は何枚くらい取得して使用しているのですか?

  • 実際に使った element_images は 1,712枚 となります。
  • 同じ画像を何回か使いまわして 40,000枚 の画像群でモザイク画を構成しています。

最も多く使われた画像はどれですか?

  • 著作権アウトなので掲載できませんが、平均色が白となる画像です。
  • 数式の画像だと全体的に白の出現頻度が多くなりますね。

画像1枚当たりが担う領域を大きくしていくとモザイクが崩れてしまわないですか?

  • 考えなしにやると崩れるので、最初にサイズを計測しました。
  • 詳しくは前述「サイズが大きくなった理由」をご参照ください。

ベクトル比較の仕方を教えていただけますか?

  • 説明を省略した部分なので、理論面は上記スライドを見ていただければ良いかと。
  • 機械学習の分類問題として扱うことができるかと思います。初学者ならCourseraがオススメです。

yuzutas0.hatenablog.com

なお、スクリプトの実際の処理は以下の通りです。閾値を決めて簡単化しています。

  • 明度 0, 1, 2, ..., 253, 254, 255 をちょうど8分割するように閾値を設けて 0 から 7 までのグループを定義する。
  • target_image の各Pixelの色が、どのグループに所属するか判定する。
  • element_images の各画像の平均色が、どのグループに所属するか判定する。
  • 同じグループであれば十分に近いものとして扱い、適当に組み合わせる。

感想

  • 至らない点が多かったですが、学びや気付きも多かったかなと思います。
  • 他の方々の発表は、各分野のプロダクトやコンテンツならではのデータ研究が多く、「これまで知らなかったことを知る」「試行錯誤して知にアクセスする」といったサイエンスの魅力を再確認できました。
  • 今回は数学枠でしたが、機会があれば別トピックでも話してみたいです。

おわりに

改めて、運営者・登壇者・参加者の皆様、素敵な時間をご提供いただき、ありがとうございました。

Courseraの機械学習コースを修了しました

修了しました 機械学習 Octave

概要

Courseraというオンライン学習サイトで公開されているMachineLearningコースを修了しました。

f:id:yuzutas0:20160319161104p:plain

もくじ

  • どんな講座か
  • 講座のアジェンダ
  • なぜ受講したか
  • 受講した感想
  • あると望ましい事前知識
  • はまりどころ
  • 最後に

どんな講座か

  • 機械学習の主要なアルゴリズムを直感的に理解して、実際にプログラミングできるように教えてくれます。また、実装前にどのアルゴリズムを使うべきかの判断、テストとチューニングの方法、大量データの並列処理といった付帯トピックも言及されます。
  • 講師はStanford UniversityのAndrew Ng(呉恩達)氏で、Googleの人工ニューロン研究プロジェクト発起人や百度首席科学者として知られています。実際にこんな風にやっていますよ!という話を交えるので、画一的で教科書的な解説よりも聴きやすいと感じました。
  • ボリュームは結構重いです。「講義および4択試験(2時間)」+「実践課題(3時間)」×「11週間」となります。

講座のアジェンダ

実際の内容は以下となっています。

なぜ受講したか

機械学習の仕組みを正しく理解する必要性を感じたからです。

学生時代に分析手法の1つとして機械学習アルゴリズムを使ったこともありましたが、直接の専門分野ではなかったので、改めて学びたいと考えました。

企画観点

  • 某所にて、機械学習の各手法の特性を無視した施策を打って、ROIを大きく下げた事例を見聞きしました。
  • バズワードに流されて誤った企画判断をしないように、仕組みと特性を把握する必要性を感じました。

開発観点

  • レコメンド機能を開発する機会があり、機械学習ツールやライブラリを使うことで、簡単に機能を導入できました。
  • しかし、さらなる機能改善・性能向上に当たり、本質を理解せずにお手軽ツールを使うことにすぐさま限界を感じました。
  • ほとんどのソフトウェアは作って終わりではないので、パラメータやロジックを継続改善できるように(そもそも継続改善することが妥当なのか判断できるように)仕組みを理解する必要性を感じました。

受講した感想

ビジュアルや動きで直感的に理解しやすい

  • 書籍だと図と文章説明と数式とサンプルコードを1つ1つ見比べながら脳内補完しなければいけないので、初学者には辛いものがあります。動画だと、その過程を講師が順を追ってビジュアルや動きで再現してくれます。
  • オフラインの講義でも直感的な理解を促してくれる優良講師はいるかもしれません。ただ、動画だとスケジュールを気にしなくて良かったり、一時停止ボタンを押すことで、安心して一歩立ち止まって考えることができます。

そのまま実務には使えないかも

内容面

  • Random Forestなど、よく使われるのに講義で解説されないアルゴリズムがあるので、網羅性の高い書籍で概要把握に当たるのが良さそうです。私は書店で何冊か読み比べて『データサイエンティスト養成読本 - 機械学習 入門編』を買いました。
  • せっかく素敵な内容なのですが、いかんせん動画なので見返すには辛いものがあります。途中途中でノートを取るか、チートシートをまとめれば良かったなぁと反省しています。

実装面

  • Octaveで試してうまくいったらPythonなどの言語を使うべし」と解説されるものの、最初から最後までPython一択だと思います。特に分析過程を記録できるIPython Notebookの存在は大きいかなと。
  • 実際にPythonのライブラリ群(Numpy, Scipy, scikit-learn)や、IaaS/PaaSが提供する機械学習サービスを活用するには、各チュートリアルに進むことになるかと思います。もしくはPythonでこの講座の課題を実装するのもいいかもしれません。

分量が多いのでかなり大変

  • 心が折れない方法 / 折れてもすぐに復帰できる方法を自分なりに確立する必要があります。
  • 複数人で勉強会形式で進めると挫折しにくい、という案がCROSS 2016 のセッションで挙がっていました。
  • 辛い分だけ、最終動画の講師の言葉に感動します。

あると望ましい事前知識

前提として以下のスキルがあるとスムーズに進むと思います。

線形代数 / 微分積分

yuzutas0.hatenablog.com

学術的な英文の読解

  • 各レッスンの演習課題は15ページほどの英文PDFで与えられます。読めないと課題に着手できません。
  • 普段から英文でドキュメントを読み書きしているソフトウェアエンジニアなら問題ないかと思います。
  • 自信がない場合は、大学受験英語TOEFL対策を試すのも良さそうです。「TOEFL学習法まとめ」が参考になるかと。

ソフトウェアエンジニアリング / コンピュータサイエンス

  • ソースコードの読み書きができないとOctaveでの演習課題に着手できません。
  • また、分野の特性上、メモリ管理などの比較的低レイヤーな話題も出ます。初歩的なCSの知識は必須かと思われます。
  • 講師の発言を聞く感じだと、そもそも受講対象としてソフトウェアエンジニアを想定しているようです。

yuzutas0.hatenablog.com

はまりどころ

実際にやってみてはまったところや困ったところのメモを公開します。 なお、利用環境は以下の通りです。

  • 利用OS:MacOSX
  • パッケージ管理:Homebrew(およびcask)
  • エディタ:SublimeText
  • ブラウザ:Firefox

Web試験の画面が表示されない

  • Firefoxだと問題・回答の画面が表示されず真っ白になることがあります。
  • Google Chromeでは問題なく進められたので、なるべくブラウザはChromeを使いましょう。

Objective-C の Syntax Highlight になる

MATLAB / Octaveのファイルは拡張子.m なので、デフォルトだとObjective-Cとして認識されてしまいます。

Sublime Text 3 で 拡張子と Syntax Highlight を紐づける方法は以下の通りです。

  1. 関連付けしたいファイルを開く
  2. View=>Syntax=>Open all with current extension as…=>[適用したい Syntax Highlight]を選択

これで .m ファイルが MATLABOctave)のソースコードとしてハイライトされます。

ex1.m の実行時エラー

gnuplot> set terminal aqua enhanced title "Figure 1"  font "*,6" dashlength 1
                      ^
         line 0: unknown or ambiguous terminal type; type just 'set terminal' for a list
  • gnuplotが利用している描画用のターミナル(Aqua/X11)が存在しないために実行時エラーが発生しています。
  • 暫定対応はいくつか考えられますが、Courseraで用意されているDLリンクではなく、HomebrewからきちんとOctaveをインストールしましょう。依存関係が明確になります。
# uninstall
$ brew uninstall gnuplot

# update
$ brew update

# install
$ brew cask install aquaterm
$ brew cask install xquartz
$ brew tap homebrew/science
$ brew install gnuplot --with-aquaterm --with-x11
$ gnuplot # => "terminal set to aqua"
$ brew install octave

# test
$ octave
$ octave:1> w = 10 + sqrt(10)*(randn(1,10000));
$ octave:2> hist(w)

submit.m の実行時エラー

!! Submission failed: unexpected error: urlread: HTTP response code said error
  • HomebrewにてOctaveの最新版(4系)を正規インストールした場合に発生します。
  • 課題スクリプトが想定しているバージョンは 3系 なので、submitコマンドの処理が失敗してエラーとなります。
  • 公式のQ&Aに修正箇所と内容が掲示されているので、その通りに修正します。
    • 対象ファイルは lib/loadjson.mlib/jsonlab/makeValidFieldName.m です。

修正前

str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];

...(中略)...

str=sprintf('x0x%X_%s',char(str(1)),str(2:end));

修正後

str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',toascii(str0(pos(i))))];

...(中略)...

str=sprintf('x0x%X_%s',toascii(str(1)),str(2:end));

参考 https://learner.coursera.help/hc/en-us/community/posts/204693179-linear-regression-submit-error

Week5 動画の翻訳

講師が話している内容と、翻訳が表示されるタイミングが大幅に乖離しています。 弊害と対応策を整理したのが以下の表です。

弊害 対応策
翻訳「数式のここを見てください」 / 画面「数式はすでに消えている」 巻き戻して内容と画面を照合する
日本語翻訳がまだ途中なのに動画が終わってしまう 諦める or 英語できちんと聞く
読むのに30秒はかかる翻訳が2-3秒で切り替わってしまう 一時停止してじっくり読む

ex6.m の実行時エラー

set: unknown hggroup property Color
  • グラフの可視化を行う際に色の指定に関するエラーが出ました。
  • visualizeBoundary.m を以下のように書き換えます。

修正前

contour(X1, X2, vals, [0 0], 'Color', 'b');

修正後

contour(X1, X2, vals, [0 0], 'linecolor', 'blue');

参考 http://blog.livedoor.jp/kmiwa_project/archives/1034089224.html

演習の内容面でつまづいたとき

以下のようなつまづきケースがあるかと思います。

  • 理解度:課題の要求は分かるが、回答に到達できない
  • 語学力:そもそも課題が何を求めているか要領を得ない
  • 精神力:単純に分量の問題で心が折れる

対処法(理解度のケース)

  • 思考の整理:紙やホワイトボードに書き出す
  • 知識の補充:動画を見返す、公式Wikiを参照する
  • 人に聞く:相談部屋を参照する

対処法(語学力/精神力のケース)

何を聞いたらいいか分からない、うまく質問を整理できない、などなど課題を理解できていない場合。あるいは聞く気概さえ喪失している場合。

あまり褒められた方法ではありませんが、Github上に演習課題を解いた人たちのソースコードが公開されているので、それらを参考にするという手があります。 実際にソースコードを読めば「あぁ、そういうことね」とすんなり理解できることは多いかと思われます。

ただ、これは規約違反のようなので、修了証明を取得するような場合には控えるべきでしょう。 本当に悩んで悩み抜いてきちんと理解できた人だけが修了者として認定されるほうが、サイトの趣旨に照らし合わせると健全と言えます。

とはいえ、あくまでも個人の余暇学習において効率的に学ぶという意味では、上記のような方法も有効です。かなりの分量があり、なかなか体力的にも精神的にも時間的にも苦しい中で、ちょっとズルをしてでも最後までやり抜くのが大事かと。せっかく関心を持ったのに、挫折して気力を削がれてしまうのが1番もったいないです。

最後に

何度も言いますが、ボリュームが大きいので辛かったです。その分だけ達成感と満足感も大きいです。 この講座を足掛かりにして、より高度な内容に踏み出して&実践に活かしていきたいと思います。 何はともあれ、「2015 December 28 – 2016 March 21」で同時期に受講した皆様、お疲れさまでした。

日曜数学会に参加しました&「プログラミングのための線形代数」を読みました

参加しました 読みました 数学

先日、日曜数学会というイベントに招待いただき、LTをしてきました。趣味で数学をやっているひと(=日曜数学者)が集まって、お酒を飲みながら研究を共有する会です。

f:id:yuzutas0:20150831233551p:plain

他の参加者のスライド

どんな話をしてきたか

f:id:yuzutas0:20150831235357p:plain

再学習の経緯

  • WEBサービスを作っているとレコメンドやラベル分類といった機械学習をやりたくなります。
  • ちょっとした実装ならライブラリとサンプルコードに乗っかれば簡単にできます。
  • しかし、がっつりカスタマイズしようとすると、線形代数を復習しておかないと苦しい場面が出てきます。
  • 線形代数とは言っても、計算問題の解法や証明の再現だけではダメで、概念を理解しておかないと応用が利きません。
  • せっかくの発表の場を得られたこともあり、上記を念頭に置いて線形代数を勉強し直しました。

再学習の内容・感想

  • 実際には『プログラミングのための線形代数』という書籍を通読しました。
  • 読んでみて「空間上のある値を別の見方に移す」のが行列であり、「線形空間における代数の作法」が線形代数と呼ばれる分野なのだと、自分なりに理解しました。
  • この理解は間違っているかもしれませんが、単なる数字の羅列・無味乾燥な手続き処理だったものに意味が与えられたということが、自分にとっては大きな一歩でした。
  • 読み進めるうちに「学生時代にやったあの計算や証明はこういう意味だったのか!」という納得感と感動を覚えることが何回かありました。

書籍の内容

目次は次の通り。基礎学習はほぼ網羅していると言っていいのではないでしょうか。

  • 1章:ベクトル・行列・行列式 - 「空間」で発想しよう
  • 2章:ランク・逆行列・一次方程式 - 結果から原因を求める
  • 3章:コンピュータでの計算(1) - LU分解で行こう
  • 4章:固有値・対角化・Jordan標準形 - 暴走の危険があるかを判断
  • 5章:コンピュータでの計算(2) - 固有値計算法

書籍の特徴

f:id:yuzutas0:20150831233716p:plain

図や日本語での説明がしっかりしているのに加えて、数式と照らし合わせながら読み進めることができます。私が学生時代に指定された線形代数のテキストは数式だらけ+略しすぎて何が言いたいのか分からない図しかありませんでした(単に私の学習不足によるところも大きいでしょうが)。一方で、分かりやすさを売りにする書籍は扱う範囲や数式が浅すぎて実用に耐えられなかった印象があります。本書は両者の不満を解決していたので、非常に助かりました。

f:id:yuzutas0:20150831233832p:plain

また、何と言っても素晴らしいのが「この数式や説明が分からなかったら、XXXについての理解がきちんとできていないからだ!XXXページを読み返せ!」という注釈が大量についている点です。ついつい分かったフリをして読み進めがちですが、このように何度でも戻って復習できる工夫がなされているので、着実に土台を固めることができます。

書籍の注意点

  • 「プログラミングのための」と銘打っており、演算処理に関する言及もあるものの、どちらかというと「実務で使えるように概念を説明する」という側面の方が強いです。なので、プログラミングをしない人でも本書の対象になり得ます。
  • 説明用のサンプルコードは書いてあるものの実用に耐えうる内容ではなく、結局は有名ライブラリを使ったり、数学の専門家に依頼するように、という注意書きがされています。なので、書籍に書いてあるアルゴリズムをそのまま使うのではなく、あくまでも概念を理解するためのものだ、という認識で読む必要があります。
  • どうしても理屈の説明がメインなので、線形代数の問題をがっつり計算するという書籍ではありません。実際に手を動かして計算することで理解が進むのだ!という人は問題演習に特化した書籍の併用をお薦めします。

その他

参加者へのメッセージとして「私と同じような初学者がいたら本書を勧めたら良いのではないでしょうか」「数学の輪を広げるには、レコメンドアプリを作って一発儲けられないかな、みたいなことを言っている俗人を引き込むことも有効かもね」という話をしました。

プログラミングのための線形代数

プログラミングのための線形代数

おわりに

ちなみに、私が参加したのは第2回目で、今後は2〜3ヶ月に1回くらいの頻度で開催するとのことです。興味のある方はぜひ参加してみてはいかがでしょうか。