データ・サイエンティストは可視化の夢を見るか?

Does Data Scientist Dream of Visualization?

やっと一冊終わったよ

今晩和。
移植のほうが暗礁に乗り上げたのですが、折角の休日を活かさない手もない。
そこで中断していた競プロの独学に復帰しました。
そして、やっと写経が終わったのです。


いやあ、着手したのが今年の 3 月 10 日なので、足かけ4ヶ月掛かってしまったことになります。
中断の原因は、本業の負荷が高まってきたためです。良くないですね。

初歩的なテクニックをひととおり学習したはずですが、とてもとても血肉となっておりません。
ですが、このようなプログラミングのプロジェクト群はほぼすべて Gollum の管理下に置いてあります。注釈とか付けやすい筈なんですよ。ですから復習がてら、今度は写経したソースコードの読解と注釈に傾注していきます。

浅学非才の身でもできることはあるはずです。
その実現のためにも、できる範囲ではありますが研鑽は惜しみません。
逆に言えば、分不相応なことには二度と手を出すつもりはありません。
もう、人生も半分を折り返してしばらく経ちます。
自分にできることをひとつひとつこなすだけで精一杯ですよ。
そして、それだけできちんと余所様のお役に立てるはずです。

移植の困難さ

今晩和。
相関解析システムの Unity への移植、早々に頓挫しそうです。

f:id:renpoo:20170717205426p:plain


要は、処理パラダイムの異なる言語環境、というよりゲーム・エンジンに科学計算アプリを移植することの困難さに直面しています。
具体的には、先達に御教示いただいた「テッセレーション・シェーダー」で表示系を実現しようとしたんですが、此処に『相関関数』の解析計算を組み合わせるのが非常に困難なんですよね。シェーダー言語の中に、ふつうの C# スクリプトのインクルードするのに失敗してしまったのです。

此処でふたたび助言を仰いで、ひとつひとつ困難を乗り越えて移植を実現することも可能でしょう。
でも、そんなことをしてどれだけのユーザーが使ってくれるのか?

MATLAB でコーディングしたオリジナル版は遅いです。
3D surf の回転などの操作も遅いです。
ですが、科学計算の結果グラフに必要な出力値のチェックなどは標準で組み込んであるので、カンタンにできる。
このシステムを使うようなユーザーも MATLAB は理解している人が多いでしょう。

さあ、どうするか?
思案のしどころです。
結論は急がないことにします。
ほかにもやるべきことは山積しているので。

反省

今日和。
ちょっと本業が忙しくてバタバタしております。

それにしても反省。
いろいろと考える割りには利他行の実践がたらないなあ、と。
いまの自分の知識や能力でもできることがあるのでは?
とりあえず、なんらかのかたちにして世に問うべきでは?

たしかにその一環として「本業」もありますし「移植」もありますが、それらはできるだけ早々に片付けて、もうちょっと広いターゲット層を狙いに行くような活動をしたいと願っています。
まだまだやれること、あると思うんです。

Unity への移植を開始する

f:id:renpoo:20170704073509j:plain


おはようございます。
やっと、相関解析システムの Unity への移植を始めました。
某方面で助言をいただけたこともあり、プロトタイピングも比較的スムーズに進んでおります。
あとは相関関数の実装や、音声ファイルなどの読込などの実現、そして GUI の整備なんですが、正直 Octave のコードを借りようかなあ、と悩んでいます。勿論、このシステムも GPL で公開することを念頭に。
ちょっと関係各方面にお伺いを立てねばなりませんね。

半自動化 OCR

おはようございます。
我が家の『自炊書籍』も 500 冊近くになりました。
ScanSnap SV600 で丹念にスキャンしてくれている母に感謝です。

さて、そのようにして作成した自炊 PDF、そのままだと取り扱いにくいです。
以前述べたとおり、論文など PDF の管理(マーキングやコメント)は "Mendeley" に一元化したのですが、偶にはキーワード検索したくなる。そういうときに『大雑把にでも』OCR しておくことは大変重要です。現在の OCR の認識精度はそれなりものに留まっていますが、それでも「粗方、検索できるように」文字認識しておくことは、あとあとのことを考えるとかなり大切な下準備になっています。
将来的にもっと精度の高い OCR が出てきたら、再認識させれば好いことですからね。

この作業、これまで手でやってきましたが、定型作業であることもあって面倒です。
さらに今回、旧約・新約聖書を分冊して取り扱う必要があったので、一気に数十の PDF を OCR に掛ける必要が出てきました。そうなるとケアレス・ミスの可能性だって出てきます。

そこでこの文字認識作業の工程を自動化できないかどうか挑戦してみました。
いくつか調べて試してみたのですが、結局一番便利で安定しているのは "UI Automation PowerShell Extensions" によるバッチ処理の実現でした。寡聞にして知らなかったのですが、"PowerShell" は近年 Windows OS に実装されたシェル環境です。Unix ユーザーにとっては、これまでの MS-DOS コマンドプロンプトより格段に使いやすいです。

"UI Automation" については、此の辺を参考にしてください。
(前者のページは近々に閉じてしまう模様です。)

uiautomation.codeplex.com
github.com


あれこれと解説していても仕方ないので、今回作成した『半自動 OCRスクリプトを公開します。
工夫せざるを得なかったのは、ID を参照してのマウス・アクションのシミュレーションが意外と難しかったので、キー・アクションで望みの処理フローを実装したところです。あと、自炊 PDF によって数百ページとか数ページとかページ数の多寡が違いすぎるので、OCR 処理各工程の時間が読めず、しかたなく Start-Sleep でキー入力待ちにして、人間が次の処理の実行を判断するようにしました。


まだ多少不便ですが、かなりの改善がなされました。
この PowerShell の活用による作業プロセス自動化は今後も大いに役に立つことは間違いないですね。

# Import-Module "C:\Users\renpoo\UIAutomation\UIAutomation.dll"


Clear-Host;
$Path = "~\Downloads\";
cd $Path;

ForEach ($file in Get-ChildItem $Path -Name)
{ If ($file.Contains(".pdf"))
  {
    $file.fullname

    Start-Process e_Typist -PassThru;

    Start-Sleep -s 20;

    $process = Get-UiaWindow -Class 'eTypistClass';

    Start-Sleep -s 3;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_F)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_F)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);

    Start-Sleep -s 3;

    $process.Keyboard.TypeText( $file );

    Start-Sleep -s 3;

    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::TAB)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::TAB)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);

    Start-Sleep -s 5;

    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);

    Start-Sleep -s 3;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_L)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_A)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);

    Start-Sleep;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_R)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_L)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_A)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);

    Start-Sleep;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_R)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_M)
    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::SHIFT)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::F6)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::SHIFT)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN)

    Start-Sleep;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_L)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_A)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);

    $newfile = $file.replace( ".pdf", "*.pdf" );

    Start-Sleep -s 3;

    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::TAB)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);

    Start-Sleep -s 5;

    $process.Keyboard.KeyDown([WindowsInput.Native.VirtualKeyCode]::MENU)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_F)
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::VK_X)
    $process.Keyboard.KeyUp([WindowsInput.Native.VirtualKeyCode]::MENU);
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);

    $process.Keyboard.TypeText( $newfile );
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);
    $process.Keyboard.KeyPress([WindowsInput.Native.VirtualKeyCode]::RETURN);

    Start-Sleep -s 10;

    #break
  }
}

移植のために

おはようございます。ずいぶんな御無沙汰です。
ちょっと本業に忙殺されており、なかなかこちらに記事を書けない日々が続きました。


f:id:renpoo:20170226195828p:plain

f:id:renpoo:20170226195833p:plain


ここ数年間傾注してきた『相関解析システム』、より多くの方たちに使っていただくには MATLAB から、より一般的なプログラミング言語に移植しなくては、と考えるようになりました。

そこで目星をつけたのが "Unity" です。
相関解析に必要な物理数学は比較的単純なモノばかりですから理解もできるようになりましたが、音声ファイルの認識など足まわりはこれから勉強しなければなりません。そこで「参考になるだろう」と "Octave" のソースコードを拝見することにしました。

これから本業のかたわら、移植作業を進めていきます。
やっぱり、日々プログラミングしていないと腕が鈍るので。(汗)
当然、GitHub で公開しますよ!

逆行する社会

今日和。おひさしぶりです。
ここのところ、読書ばかりしています。本業の参考資料が中心です。
正直、仕事の本ばかりだと辟易してきます。そこで別種の本を、と、こんな本を選んでみました。
親友のススメで、いまさらながらにして『カイゼン』や『かんばん方式』に興味を持ったからです。

カンバン: ソフトウェア開発の変革

カンバン: ソフトウェア開発の変革

これはなかなかの良書ですが、エリヤフ・ゴールドラット博士の提唱した TOC 理論では不足だった部分にまで、プロジェクト・マネジメントを改善しようとしています。

ザ・ゴール ― 企業の究極の目的とは何か

ザ・ゴール ― 企業の究極の目的とは何か

ザ・ゴール 2 ― 思考プロセス

ザ・ゴール 2 ― 思考プロセス

チェンジ・ザ・ルール!

チェンジ・ザ・ルール!

クリティカルチェーン―なぜ、プロジェクトは予定どおりに進まないのか?

クリティカルチェーン―なぜ、プロジェクトは予定どおりに進まないのか?

ザ・チョイス―複雑さに惑わされるな!

ザ・チョイス―複雑さに惑わされるな!

ザ・クリスタルボール

ザ・クリスタルボール

ゴールドラット博士の論理思考プロセス―TOCで最強の会社を創り出せ!

ゴールドラット博士の論理思考プロセス―TOCで最強の会社を創り出せ!


まだ読書が中途なのであまりたくさん感想を述べる気はありません。
ですが、ICT の世界では並列分散処理系が当たり前となった時代に、わざと仕掛かり量を制限して、逆にスルー・プットを恒常的に改善させ、チーム・メンバーの QOL やモティヴェーションを改善する、それらの施策の論理的帰結として生産性向上がある、というのはやっぱり王道の働き方に見えます。

そんな時代の趨勢に逆行するかのような社会が国際的に散見されますが……、その先にあるのは衰退だけでしょうね。
一時的には誤魔化せるでしょうが。


同時に、あの有名な Paul Graham の『ハッカーと画家』にも目を通しました。

彼のテクストの邦訳は有志の手によるものが此処に置いてありますが、とりあえずお布施のつもりで 1 冊買いました。
http://practical-scheme.net/wiliki/wiliki.cgi?naoya_t%3Aポール・グレアムのエッセイと和訳一覧

やはり触発されるところ多々です。
いずれ、稿をあらためてふたたび取り扱いたいと思います。

ビジネスマン向け入門書の世界

今日和。

良書を乱発している永野 裕之 氏の啓蒙書をざっと眺めてみました。
なかなか良い内容なんですが、いかんせん軽いですね。

ビジネス×数学=最強

ビジネス×数学=最強


同氏では、こちらのほうが面白く読めました。
もう何度か読んでいます。

大人のための数学勉強法 ― どんな問題も解ける10のアプローチ

大人のための数学勉強法 ― どんな問題も解ける10のアプローチ


これ、要は読者ターゲット層の問題ですよね。
ちょっと愕然とする気分だったり………ううむ……。

オープン・データを解析するにも前処理に手間暇がかかる

今日和。
見事なまでに徹夜明けです。
丸一日かけて、件のオープン・データ(内閣府世論調査)を統計アプリで分析しやすいように整形してみました。

f:id:renpoo:20170410153809j:plain

いやあ、手間暇かかりましたね。
政府系のオープン・データを観察するのは初めてのことだったのですが、かなりの面倒さです。
最初のうちはどうしたらいいのか分からないので、Excel で手を動かして試行錯誤をくり返していました。親友に教わった「アルゴリズムの手順に従って条件付き書式で色分けをしてみる」などもやってみました。

でも、これはスクリプトで処理しないと、結構大量なデータ数なので大変です。たとえば、この質問票1は 2010 年度から 6 年分存在します。
そこで慣れてもいない Python を使って文字列処理することに決定。
しばらく Jupyter Notebook の上で、段階的にフィルタリング処理を積み重ねていきました。
そうすると一夜明けて目途が立ちます。
要領を掴んだ、と思ったのです。

ですから、そこからは emacs にエディタを移し、一括のバッチ処理スクリプトとして、さらなる改造を加えます。そして先程、第一段階としての質問票1について前処理が終わりました。
試しに、ちょっと Excel の「区切り位置」でフィールドをバラしてやり、Tableau に取り込んでやると、面白いように多角的な分析ができます。
ああ、苦労した甲斐があったなあ〜。

今回の教訓は、複数年にわたる公共系のアンケート・データにありがちなことなんでしょうが、質問項目が微妙に変わったりして、データの突合が難しいことでした。ですから、イヤになるほど文字列置換を駆使して辻褄を合わせています。それと階層構造のフィールドもあったので、それをひとつのフィールドにまとめるために、ちょっと技巧的なことを、ぎこちなくも行いました。
スクリプトのソース・コードは相当汚いです。
ほかの質問票にも挑戦する過程で、なんとか推敲してやりたいと思ってます。


しかし、勉強になりましたね。
Johns Hopkins の MOOCs "Executive Data Science" のコースで教わったとおり、単に公共データを借りてきて分析するにも様々な問題に直面します。
下手くそながら、一定の解決を見たのは良い経験になりました。
人生、いろいろやってみるものですね。

世論調査のオープン・データを眺めて思案する

今日和。
先日、ラジオ・ニュースで内閣府の『社会意識に関する世論調査』についての報道がありました。
興味を持ったので、内閣府サイトに行って該当データをダウンロードしてきたんですが、中身を見てビックリ!
三重クロス集計の、しかもパーセンテージに変換してあるデータになっています。
なんか取り扱いにくいなあ、と思うのは私だけでしょうか?


そこで検索して行き当たったのがこれ。
R言語で統計解析入門: クロス集計表から「スタック」形式のデータフレームへデータ変換 梶山 喜一郎
R言語で統計解析入門: 多重クロス表:質的データから3変数のクロス表(三重クロス表)を作成する 梶山 喜一郎


成る程、多重クロス集計からでも元データ相当のテーブルが生成できるんですね(そりゃそうだ)。
該当 csv には母数の記載があるので、元のクロス集計表を復元することは可能です(パーセンテージにした段階で有効数字が丸められているので、多少の誤差は混入していますが)。でも、これらのアンケートを経年推移を観察できるようなデータにまとめてみたい。

そこで参考になるのが『世界銀行』の統計データです。
World Development Indicators | Data

こちらの中身を観察すると、複数のカテゴリーにわたる経年データをどのように記述すれば、統計アプリで取り扱いしやすいか一目瞭然です。


内閣府の『社会意識に関する世論調査』が現在の質問様式になったのは平成 10 年度頃からの模様です。
ですが、質問項目についても多少の異同は存在するでしょう。
そういったことを勘案したうえで、如何に一覧表にまとめ上げるか、この数日、思案に暮れています。

残念な自己啓発書の世界

今日和。
スキマ時間に自己啓発書を読んでみました。

あまり批判的なことをいっていても仕方ないので、端的にまとめますが「十分の一の分量で済む内容」でした。
ひさしぶりに勝間 和代 女史を想起しましたね。
本書は、著者の交遊(とされている人脈)から次々と匿名の人物を引き合いに出しては「教訓めいたエピソード」を展開するといった体裁になっています。ですが、そこで語られるトピックを具体的にどのように実践するかの記述はまったくといっていいほどありません。

へえ、こういうふうにしてもタイトルや惹句によって、あるいは出版社のプロモーションによって、ベスト・セラーを作り出すことは可能なんだな、ということが理解できました。中学生の頃に読んだ、中島 梓 先生の『ベストセラーの構造』を思い起こして反省しました。わたしがこの本から得られた教訓は、この著者の書籍を二度と購入しない、の一点に尽きます。

なにごとも勉強になるものですね。

頭をヒネる写経

今晩和。
「本業」のかたわら、写経を続けて「競プロ」の自習を続けています。

正直、一日に 10 題、写経するのがやっとになっています。
いまは第 16 章『計算幾何学』をほぼ終えようとしているところです。
お題としては 3DCG ライブラリ関数のような内容ですから、多少馴染みがあるモノの、そろそろ解答例がすべて書いてあるのではなく、すこしは自分でアタマをヒネらなければ、という出題になっています。「すこしは」ですが。

多少、誤記も目立ってきましたね。
まあ、IT 系書籍では珍しくないことです。
実際に、手を動かしてみればエラーは分かってしまうのだから、それに目くじらを立てるより自己解決を図ったほうが生産的です。

それでもなかなか勉強になっています。
驚くべきは、というか本質的なことですが、このような『競プロ』の問題を解くために必要なアルゴリズムは数十行、多くても百行程度ということです。その程度の簡単な処理の積みかさねで、けっこういろいろな問題を解けてしまう。ここら辺の、ロジックの簡明さとその奥深さにプログラミングの醍醐味がある気がします。

正直、まだまだ血肉化できていません。
それはそうです、まだ第 1 段階の『写経』なのですから。
でも、祈ってしまいます。
近い将来、こういった努力が実を結ぶことを。

続く写経

今日和。
「本業」のかたわら、写経を続けて「競プロ」の自習を続けています。

とにかくスピード勝負で、全体を通して復習って、そこからひとつひとつの課題を掘り下げて、深く探求していこうとしています。
何度もなんどもくり返して学習するのを念頭に。

写経を続ける

今晩和。
「本業」のかたわら、写経を続けて「競プロ」の自習を続けています。

とにかくスピード勝負で、参考書掲載のソースコードを打ち込み直すだけに専念しています。
1 日 10 題程度の進み方ですが、個人的にはまあまあ、という感じです。
とにかく小僧の手習いと思って書き写しています。

別に内容については上掲書を当たっていただければ十分なので説明しません。
でも大事なのは、競プロの問題を解くに当たっての「型がある」ことです。
引数としての配列の受け渡し方とか、要所にあたる変数はグローバル化してしまうとか、そういったことが意外と大事なんだなあ、と。
自分は学生時代から教科書や参考書は読んでマーキングするモノの、例題を具体的に紙と鉛筆で解く作業が足りなかったタイプで(してなかった訳ではありませんが)、いまになって苦労しているので、その欠点を補うために、近年は写経を率先しています。

もう四十代中盤になってしまいました。
これから学位を取るにせよ取らないにせよ、「残り時間」がどんどん減ってきているのを痛感しています。
正直、社会に出た初期のトラブルで障害を負ってしまったせいで、あまりにも大きすぎる loss をしてしまったのは悔やまれます。
でも、それもいまや所与の条件ですから、その制約のなかで最善を尽くしていくのみです。
がんばります。

『競プロ』の独学を再開する

今日和。
実は「本業」があるのですが、協業している方からのレスポンス待ちになっています。
そこで偶には好きなことを、という理由で、『競プロ』の独学を再開しました。
もう、スピード勝負、あんまり考えずに写経していきます。
何故なら、いまやっている章は学部生時代、それなりに独学したところだからです。
確認で済むところは徹底的に駆け足で。



以下は一番基本的なソート、『挿入ソート』のコードの写経です。
C++ となっていますが実質 C です。
コメント・アウトしてあるところに入力例が書き込んであるので、お手元でビルドして実行させてみると insertion sort の動作が一目瞭然で理解できるでしょう。

#include <iostream>
#include <cstdio>


const int MAX_N = 100;


void trace( int A[], int N ) {
    int i;
    
    for ( i = 0; i < N; i++ ) {
        if ( i > 0 ) printf(" ");
        printf( "%d", A[i] );
    }
    printf("\n");
}


void insertionSort( int A[], int N ) {
    int i, j, v;
    
    for ( i = 1; i < N; i++ ) {
        v = A[i];
        j = i - 1;
        
        while ( j >= 0 && A[j] > v ) {
            A[j+1] = A[j];
            j--;
        }
        
        A[j+1] = v;
        trace( A, N );
    }
    
    
    return;
}


int main(int argc, const char * argv[]) {
    int i, N;
    
    int A[MAX_N];
    
    scanf("%d", &N);
    for ( i = 0; i < N; i++ ) scanf("%d", &A[i]);
    
    trace( A, N );
    insertionSort( A, N );
    
    return 0;
}


/*
6
5 2 4 6 1 3
*/


こういうことを勉強し直して、いろいろと忘却の彼方にあったものを再確認できると、なかなかストレス発散になりますね。(苦笑)