• このエントリーをはてなブックマークに追加

  • 人工知能と人類の未来を考えてみた

    2016-03-23 20:00
    星新一賞に対して人工知能を使った小説が11作品も投稿されたというのが話題になっております。現時点では、人間の手が若干加わっているとのことですが、見事に人間の想像力というものを脅かしてくれるニュースでありました。

    今回は、人工知能に関して僕なりの展望を書いていこうと思います。

    人工知能の小説

    投稿作品と言われるものをいくつか読んでみたのですが、基本的に星新一の小説のように心が揺さぶられる要素がないことと、若干、文の繋ぎが難しそうというのが感想です。ですが、100%人間が書いたと言っても違和感の少ない文章でした。

    そして、将来を想像しながら読むということであれば、十分面白い文章だなと思いました。

    文章ということで言うと、人間かロボットかはあまり関係なくなってきているのかなと思います。すでに Twitter では人間なのかボット(自動配信ツール)なのかの区別がつきにくいという現状があります。

    そして、人工知能が作ったニュース、書籍を知らず知らずのうちに購読している。そういう世の中はもうすぐそこまで来ています。正直、星新一賞投稿作品レベル以上がキープできれば、問題無いでしょう。

    今後、各メディアの編集長は、人工知能を扱う力量が問われて来るでしょう。8割程度のクオリティで人工知能に書かせ、人間が推敲して公開する。そのような手順が基本になるのではないでしょうか。

    文章に関しての未来は明るそうです。では、音声や会話に関してはどうでしょうか。

    コラボレーションツールとは

    若い人の会話は LINE や Twitter などをはじめとするツールによるコミュニケーションがもはや主流といっても過言ではないですね。以前なら電話や会話によって、やっていたコミュニケーションもこういうツールがあると楽にできます。

    IT系ベンチャーを中心として、Slack(スラック) とか Hangout(ハングアウト)、Chatwork(チャットワーク)、Backlog(バックログ)と言われるツールが非常によく使われるようになりました。

    これは、コラボレーションツールと言って、会話や仕事のやり取りの内容、ファイルの交換履歴などを整理して残しておくための手段です。

    これらのツールを使う目的は何かというと、会議を削減・効率化することです。会議は、後でも述べますが、オーラルコミュニケーションの上に成り立つコミュニケーションで、時間や労力といったありとあらゆるものを拘束しなければ成り立たない非常に非効率な手段と言わざるをえません。

    ダラダラ会議を終わらせた、ザッカーバーグの2つの会議効率化戦略 にあるように、世界中の企業が、会議自体を削減することや、効率化を図るように試みています。

    僕は、学生時代、生徒会をやっていたことがありますが、思えば、人生においてダラダラと会議をやる習慣は、あれが最初なのかもしれません。

    ちなみに、当時気弱な僕は、生徒会は周りの圧力に屈してやったものであり、選挙活動以外面白いと思ったことは一度もありませんでした。僕は、早く帰って N88 Basic のコードを打ちたくてしょうがなかった気がします。

    今の子は、自宅で Jumper やるか Mine Craft やるか YouTube でも撮っていたほうがよっぽどよいでしょう。これらのほうが、よりみんなと協力しあって作品を作り上げる喜びを感じられます。

    オーラルコミュニケーションの終焉

    オーラルコミュニケーションは、音声を使った会話によるコミュニケーションの手段のことを言います。オーラルコミュニケーションはさらに、バーバルコミュニケーションとノンバーバルコミュニケーションに分けることができ、音声による文字情報の伝達をバーバルコミュニケーション、表情や雰囲気などによる情報の伝達をノンバーバルコミュニケーションと言います。

    オーラルコミュニケーションの良い所でもあり、悪いところでもあるのが、コミュニケーションミスが生じやすいところと、時間、労力が拘束されること。あと、仕事上非常に問題なのですが、会議費というのは、意外に請求しにくいものです。

    まず、ひとつ目の問題、コミュニケーションミスが生じやすいということですね。がんばって伝えようとしてもなんか伝わらない。議論がそれていってしまったり、雑談化してしまうなどが結果として起こります。これは、現時点では、コラボレーションツールを使って大半の問題は解決できるでしょう。将来的には、人工知能と人類がまさにコラボレーションすることで、解決していくことだと思います。

    例えば、恋愛において、ベストな告白のタイミングを教えてくれたり、喧嘩してしまった場合も、仲直りの手段を提示されるようになるでしょう。

    そして、時間、労力の拘束、会議費ですが、これらはまとめてコラボレーションツールを使えば解決するでしょう。

    このようにして、本当に必要な会話だけに集中することができるようになるでしょう。人工知能はおそらく、水道光熱のようにインフラ化して、月額固定で個人が利用できる段階までいくでしょう。

    既に、美人受付嬢アプリなどが販売されていて、仕事上、すでに人間がやるべきコミュニケーションは限らてきている。そう考えても間違いではないでしょう。

    オーラルコミュニケーションの終焉という見出しにはしましたが、人間のコミュニケーション自体は大きく進歩を遂げるでしょう。

    星新一関連ニュースまとめ

    今回は、ここで終わりです。

    星新一賞に関して、中でもよくまとまっていた、ニュースのエントリを上げておきます。

    http://www3.nhk.or.jp/news/html/20160321/k10010451071000.html

    http://pc.watch.impress.co.jp/docs/news/20160322_749364.html


  • Haskell で覚えるプログラミング

    2016-03-16 20:45
    いままで、モデルやモジュールに関して話して参りましたが、今回は、更に応用に入っていきます。理屈っぽい話が続きましたが、全ては、プログラミングができるようになるための下準備でした。

    今回は、簡単なプログラミングをしてみます。扱うのは、 Haskell という名前の言語です。 Jumper のデータを保存するサーバにも使われている現在の欠かせない言語です。

    例題として、
    ベクトル (1, 2, 3, 4) と (4, 3, 2, 1) の内積を求めよ。
    を扱ってみます。内積の計算といえば、言語処理などでもよく使われる重要な演算処理となります。内積の値が大きければ大きいほど、2つのベクトルに関連性があるということです。

    プログラミング言語を扱ったことがある人は、得意な言語でどのようなコードになるのかを想像してみてください。

    ちなみに、上の内積の計算は簡単で、
    (1 * 4) + (2 * 3) + (3 * 2) + (4 * 1) = 20
    となります。掛け算して足し合わせるだけです。他の言語だと、 恐らく、5行前後で表現できるのではないでしょうか。簡単な計算のはずが意外と書くことが多くて大変です。

    では、Haskell ではどうなるのか。でも、その前に Haskell に関してさらっと勉強していきましょう。

    Haskellとは

    まず、Haskell は関数型言語です。関数型言語は、手続き型言語と対となって説明される概念です。関数型言語は、数学で勉強する関数を組み合わせることで要件を満たします。それに対して、手続き型言語は、手続き(一連の処理の流れ、ルーチン(routine)、プロシージャ(procedure))を組み合わせることで、求める動作をします。

    Lisp、Scheme、Ocaml、Haskellなどが、関数型言語。C言語、Perl、Basicなどは、手続き型言語です。手続き型言語は、手続きのことを「関数」と読ぶことが多いですが、ほとんどの「関数」は、関数ではありません。今回は、関数か否かの話は割愛します。

    次に、Haskell は静的型付け言語です。僕が、Haskell を好む理由は、こちらにあります。静的型付けによって、複雑なプログラムもミスが少ないことを保証することができるのです。こちらも、詳しい話は割愛します。

    インストール

    https://www.haskell.org/platform/ からインストーラをダウンロードしてください。

    ダウンロードが完了したら、ダブルクリックしてインストールしてください。あまり大変な作業は無いかと思います。

    ghci

    ghci を使うことで簡単に Haskell のプログラミングを触ることができます。

    コマンドプロンプトまたは、ターミナルを開いて、以下のコマンドを打って開始です。
    ghci

    これだけです。ghci> という表示が出てきたと思います。

    では、簡単な計算をしてみようと思います。
    1 + 1

    2 と出てきたら成功です。

    では、どんどんやっていきましょう!

    リスト操作

    Haskell において重要なデータ構造が、リストです。リストを制するものが Haskell を制するといっても過言では無いでしょう。
    let a = [1, 2, 3, 4]
    これで、リストの定義は完了します。let は、「…を〜させる」という意味の単語ですね。この場合、a を [1, 2, 3, 4] と定義するという意味になります。

    [1, 2, 3, 4] というのがリストです。他の言語とほとんど同じですね。
    head a
    とすると、先頭の 1 が取り出せ、
    tail a
    とすると、[2, 3, 4] が取り出せます。
    last a
    の結果は、4 です。

    なんか、退屈ですね。。。こういう関数は、使いながら慣れていけばよいので、こういった関数は、今覚える必要はありません。

    リストという複数の要素を扱うための型があるということを認識できればそれでよいです。

    foldr

    foldr (フォールドアールと読みます)は、畳み込みという名前の付いた関数です。先ほどの a を操作してみましょう。foldl(フォールドエル)もありますが、ほとんど同じものだと考えて構いません。
    foldr (+) 0 a
    としてみてください。結果は 10 になります。この場合は、foldl と foldr と書き換えても結果は同じになります。総和(sum、サム)を計算するロジックだと思ってください。

    ここで、他の言語で総和を計算することを考えてみてください。恐らく、数行のコードになるかと思います。それが、学校で習う数式のようにシンプルに1行で表現できてしまいました。

    これが、Haskell のリスト操作に対する強力さであります。

    上の結果がなぜ 10 になるのかを説明するのは、今回の趣旨からそれますので、fold (+) 0 はリストの総和を求める関数ということを覚えておいてください。

    zip, zipWith

    zip(ジップと読みます)というと、一番最初に思いつくのは、ジップロックでしょう。または、人によって、チャック(zipper、ジッパー)のことと思うかもしれません。どちらも語源は一緒です。

    zip というのは、2つのものを一緒にすることを短い単語で表現しています。
    zip [1, 2, 3] [-1, -2, -3]
    とすると、
    [(1,-1),(2,-2),(3,-3)]
    が返ってきます。

    (1, -1)などは、タプルと言って、前にやったようにペアのことだと捉えていただければよいです。しかし、これでは、あまり、メリットが感じられません。では、zipWith という強力な関数を使ってみましょう。
    zipWith (+) [1, 2, 3] [-1, -2, -3]
    zipされた、ペアに対して足し算(+) が適応されると解釈してください。結果は、
    [0, 0, 0]
    になります。どうですか、ピンときましたか?

    いよいよ

    やっと、ベクトルの内積を計算する準備ができました。foldr と zipWith を組み合わせることで実現しそうですね。

    まずは、ベクトルを Haskell のリストとして表現します。
    let b = [1,2,3,4]
    let c = [4,3,2,1]
    そして、
    let dot x y = foldr (+) 0 $ zipWith (*) x y
    とします。掛けてから足し合わせる。これで、内積が求められますね。
    dot b c
    すると
    20
    できましたね!

    手続き型の言語では、ループを最初にイメージして、配列から1つずつ要素を取り出して操作する習慣がありますが、Haskell では、リストを使って要素をまとめて扱うということをします。

    こういった習慣や考え方のことをパラダイムと言ったりします。プログラミング言語をマスターするということは、まさにこのパラダイムを頭に馴染ませるということに他なりません。

    参考書があるとすると、その参考書を二周三周するか、同様の書籍を数冊読みこなし実践するうちにようやくパラダイムが頭の中にできあがり、プログラミング言語をマスターするということになります。

    今回はここまで。皆さんも諦めずに、どんどん自分なりに課題を見つけて取り組んでみてください。
  • モジュールの実装とユニットテスト

    2016-03-08 20:00
    情報処理技術者試験も近くなって参りました。多くの方が必死に勉強されていることと思います。

    今回は、モデルから一段階昇華させていきます。ちょっと難しいかもしれませんが、一部、試験の範囲になっているものもあるので、勉強がてら読んでみてください。

    モデルのひとつの結晶、塊のことを「モジュール(module)」と呼びます。似た言葉なので、一度聞いただけでは、訳が解らないでしょう。

    これは、化学に例えるとわかりやすいかもしれません。原子(atom)が、モデルだとするならば、分子(molecule)がモジュールと言えるでしょう。

    ソフトウェアとモジュール

    モジュールは、ソフトウェアの大事な構成単位です。モジュールが組み合わさってソフトウェアになります。ソフトウェアを構成するどのモジュールが欠けても、基本的にソフトウェアは動きません。

    チームでソフトウェアを作るときに、プログラマごとに作成するモジュールを割り振ります。プログラマは、与えられたモジュールの作成に勤しみます。そして、それぞれ、完成したモジュールを組み合わせてソフトウェアが完成するという流れです。

    ソフトウェア構築の詳しい流れは、共通フレーム2013に書かれています。一度目を通しておくとよいでしょう。

    ユニットテストは書くべきか

    基本的にモジュールでソフトウェアが構成されます。では、「きちーっと設計書通りモジュールを作りましょう」で基本的に議論が終了します。

    でも、これで終わってしまったら、読者が怒り出すかもしれないので、もう少し深堀していかなくてはいけませんね。

    最近、ブログやツイッターで困った議論が勃発していて、もはや炎上といっても過言ではないでしょう。その議題は、「ユニットテスト(unit test)は書くべきか」です。

    ツイッターでの議論は、基本的に長く書けないですし、みんな他人事なので、まともなレトリックを使って書いているわけではないでしょうが、ひどいなと思うことが一つあり、後ほど述べていきます。

    ユニットテストとは

    ユニットテストとは、作成したモジュールの動作が正しいかどうかを、人間による目視でチェックするのではなく、プログラムによって判定する方法のことを言います。

    モジュールへの入力に対して、こうあるべきだという出力をテストとしてプログラムします。そして、実行すると、記述したテストが順番に実行されていきます。テストに通ると緑色、通らないと赤色の点が画面に出力されていきます。

    赤い点が、緑色に変わるまでモジュールを改善していきます。ここまでが、ユニットテストを使った開発手法の概要となります。

    今のところメリットが多いように感じることでしょう。目視でのチェックがいらないですし、機械的にやってもらえれば工数が減るような気がします。

    しかし、デメリットももちろん生じるのですが、これに関しては後述します。

    二元論に陥る愚かなプログラマ

    ユニットテストに関して勉強した後に、もう一度先ほどの「ユニットテスト書くべきか否か」の議論に戻ります。

    世の中の議論には、二元論というのがあります。シンプルの極みである二元論というのはどのようなものでしょうか。

    「人工知能によって仕事がなくなるか否か」「成功するにはポジティブであるべきか否か」「今日の昼飯はラーメンか牛丼か」「ラーメンならば、醤油か塩か」

    こういう二元論に陥るのは、社会やプログラムを設計する人にとって非常に危険なことです。多様な社会や、プログラミング手法は、無限次元で構成されているはずです。それに対して、二元論というのは、一次元の議論です。二元論に陥るということは、「たったの1次元しか僕らは考えられません」と自分の能力の無さを露呈することになります。

    第一線で活躍しているプログラマもこぞって「書くべきか否か」の二元論争に巻き込まれているのを見て、なんだか悲しいなというのが僕の感想です。

    どうあるべきか

    まず、いきなりユニットテストに目を向けるのでは落とし穴にハマる確率が高いです。もっと、高い視点で物事を見ていかなければいけません。

    ソフトウェアは、通常作ってリリースしたら終わりではないので、数年から数十年のマイルストーンにおいてどのような運用をしていくかを考慮した上で、設計していかなくてはいけません。

    その中で、ユニットテストがどの程度工数を掛けられ、どのような成果がでるのかを見極めなければいけません。ユニットテストは無償でできるものではなく、かならず工数に上乗せされるものです。そのコストに見合ったものになるかは、数年経たないとわからないかもしれません。きちーっと見積もる必要があるでしょう。

    そして、ユニットテスト自体も運用していかなくてはいけないことを忘れてはいけません。仕様変更するたびに、ユニットテストの内容も変わっていくことでしょう。その度に、工数が掛かることを常に忘れてはいけません。

    この時点で軽く数次元の考えるべき要素が頭の中で思いつくことでしょう。二元論に陥るとこのような思考はできなくなります。

    ドライバとスタブ

    ここで、ドライバ(driver)とスタブ(stub)に関して復習してみましょう。どちらもテストにおいて必要になる知識です。

    作ったモジュールに対して入力して、出力を受けとるプログラムをドライバと言います。ドライバによってテストしたいモジュールを動かす(ドライブする)のです。ドライバによって入力した値が、モジュールを通じて変換され、適切に出力されるかを見ればよいです。

    図式にすると、ちょうど、真ん中にテスト対象のモジュールが来て、周りをドライバが囲んでいるような形になります。このようにして、真ん中のモジュールが周りのモジュールと協調しあって動くことを確認できます。

    次にスタブですが、ちょうどドライバと逆の概念になります。先ほどの真ん中のモジュールが仮の動きをスタブとして振る舞い、入出力を行います。

    入力側のモジュールと、出力側のモジュールが完成している場合に、それぞれのシステムが協調しあって動くことを確認することができます。

    図式もドライバのものとは逆になるでしょう。真ん中にスタブが来て、周りに作成したモジュールが配置されたような形になります。

    テストをするには

    ドライバとスタブの話をしたのは、ユニットテストでも使うからです。イメージしていただいた方にはお解りいただけたと思いますが、テストをするには、各モジュールの入力と出力が明確に定義されている必要があるということです。

    入力と出力が定義されていないものは、ドライバやスタブによってテストすることができません。なので、テスト不能ということになります。入力に対して出力が曖昧なもの、または、頻繁に変更されるようなものは大変です。

    例えば、Rails などのフレームワークでも、テストのための便利なライブラリを入れることができます。そして、関数やメソッドの動作チェックはもちろんのこと、ブラウザ上の UI を操作した時の挙動とかもチェックできます。とても便利ですね。

    このように便利なライブラリがあるので、何でもテストに落とし込んでしまいがちです。しかし、UI の操作などの頻繁に変わるものや、ユーザによって表示が切り替わるものに関しては、よく考えてユニットテストを実装しないと後々大変なことになるでしょう。

    ソフトウェア開発におけるコスト感

    ソフトウェア開発において、一番大切なのはプロジェクトの成功です。ユニットテストを書くのは、あくまで一部でしかないということです。プロジェクトの成功のためにあえて、ユニットテストを書かないというのも一つの選択かもしれません。

    期間、納期、予算、工数、人員、技術などあらゆるパラメータを考慮した上で、ユニットテストを書くべきかは考えるべきでしょう。そして、「なるべくユニットテストを書くこと」という曖昧なものであれば、基本的に、後々ユニットテストは運用されなくなるので止めたほうがよいか、仕様を満たすために作ってすぐ捨てる程度のものとして捉えたほうがよいでしょう。

    ユニットテストを書く範囲に関して明確な指針をつくることです。設計書やタスクごとにどの範囲でテストを書くべきか・今後も運用するのかをきちーっと明記することです。下手に運用するとユニットテストが仕様変更に追いつかなくてプロジェクトが破綻するという事態に繋がります。

    何事もメリットとデメリットのトレードオフによって成り立っています。それをきちーっと理解したうえで生活していきたいものです。

    ではまた来週。