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

前回のポストを見返して

統合失調の予兆な気がする。アカン。

人工知能と貧困と覇権

駄文

最近の人工知能を "人工知能" として抽象化して語られることに違和感がある。 人工知能が脅威か?みたいな議論はそれが流行るたびにあった。 少なくとも僕の生きている間ではこれが2回目で、1回目は "探索" が人工知能の正体だったとき。 将棋でボナンザが台頭して一般人を軽く超えてきたと同時に、ターミネーターが人間の脅威になるという議論はいくつかあった覚えがある。

今回も "ニューラルネットワーク" が人工知能の正体で、それをブラックボックス化された状態で議論が巻き起こる。 正体を知っているひとからすると、「人工知能が怖いか?」みたいな質問はあるいみ滑稽で、 ソートのアルゴリズムは怖いか?とか、2次方程式は怖いか?とかという質問と同様にとらえることができる。 きっといつか専門外の人たちが、将棋の AI は想像を超えた量の手を読んでいると理解するように、 想像を超えた量の分類で日本語と英語を翻訳しているとなんとなくその存在を認められるようになる。 このあたりが、きっとマルチラリティの一つずつなのではないだろうか?

普通の人間にできることはそこまで多くなくて、将棋が趣味の翻訳家の友人ぐらいなら近いうちに作れてしまうかもしれない。 そしていつのまにか周りがそんな人達に囲まれた将来は、きっとシンギュラリティと言えるだろう。 たぶん人間が一日に会ったと認識する人数もそれほど多くないので、囲まれるという状況もきっとスマホで作れる。

これを思ったのは、正月の帰省で ニッポンのジレンマ を見たから。 Twitter の反応を見ると、議論そのものに文句を言っている人がいる。 横文字ばっかりとか、具体的に語れよとか。生放送ではないのだけれど。

同時に思い出されたのが年末に マンガワン の配信で見たオメガトライブ。 この中で、梶秋一という人物が自身の従える暴走族の前で総理大臣になると宣言する。 このシーンは、主人公の吾妻晴が種の入れ替わりとかの抽象的な話で解いた後に、 梶くんが「こいつらバカだから具体的なことしかわかんねーよ」という流れから続く。 「つまり俺が総理大臣になる」というのは、バカの象徴の暴走族でも具体的にイメージできる事象なのだ。 きっと梶くんならあの番組を見た後に、バカでも心が動くまとめをしてくれる。

年末に帰省して小中学校の頃の人間と会うと、相対的な貧困とはこういうことかとよく理解できる。 彼らは衣食住に不安は無いだろうし、携帯も持っている。結婚もしていてある意味自分よりも幸せそうだ。 ただ、僕の仕事については「なんか難しいこと」らしい(わかった気にさせるのは得意だと自負していたのだが…)。 タバコと酒と昔話で共通のものを見つける会話と、大学時代の研究や仕事で違う世界を共有する会話は、貧困に対して十分に相関があるように思える。 一応断っておくと、仲が悪いとか見下しているとかそういう話ではない。「幸せそうだ」と書いたのは皮肉でもなく単純に羨ましい。

「政治的な判断は Truth に従うか、 Post Truth に従うか」みたいな質問は、たぶん日本のほとんどの人間が理解できない。 理性と感情と言っても、むず痒い気分の人のほうが大多数で、共通のものを見つける会話ではまぁ全く通じないだろう。 抽象的な言葉はそれだけで分断を引き起こす。 大学入試の人工知能で人間の国語の能力の低さがわかったというのは、そのあたりの感覚値と合っている。 識字率が高いというのは字が読めるというだけで、抽象度の高い文章を理解できるのはそこからさらに絞られる。 バカ競争が原因というのは一理あるが、単に発見されただけという仮説も十分ありうる。 どちらにしろ、人間は思ったほど知的な生き物ではないらしい。

トランプというのは、そのような現実の多数に支持されたのだと思う。ヒラリーの方が正しいとかそんな話ではない。 抽象的な議論に触れる機会がある人たちは、どちらが多数なのかを勘違いしやすい状況にあるのだと思う。 ヒラリーの話す言葉は聞き取れはするが、暴走族の前の吾妻晴のように意味不明な宇宙語を話しているように聞こえる。 一方で、トランプは具体的にメキシコとの国境に壁を立てると言って、つまりはかつての偉大なアメリカにする。わかりやすい。 「偉大なアメリカ」というのは、理解できて心が動くギリギリの抽象度で、なおかつ昔話なのである。 どちらの思想が正しいとかの対立ではなくて、理解できたかできないかの違い。 我々と近い言葉を話すトランプは同じ族の仲間であり、理解不能な宇宙人は別の種族。 どちらに投票するかと言われれば、共通のものを持つ同族に投票するだろう。

戦争に関して言うと、もうドンパチやるような戦争は、覇権を争う上では主ではなくなると思っている。 今は Google や MS, Amazon がアメリカにあるが、情報を握り合ってうまく活用した方が覇権を取ると、 いつのまにか別の国の似たような企業が圧倒的なシェアを持つようになる。 それ以外の国々はきっといつのまにか丸裸にされ、やりたい放題に送り込まれて、気づいたら時代が変わっている。 覇権の圏内に入れない国々は、生産性でまともに太刀打ちできず、ストレスによって種として自ら衰退する。 去勢薬のバイオテロなど行わなくとも、人口減少はすでに起こっている。

世界で1人ぐらいは、人道的な非難を避けつつ他の種族を滅ぼす方法を考えているだろう。 覇権国家がシンギュラリティのメリットを享受する一方、 抽象論で時間を潰している国は、社会学的な戦争で意外とあっさり淘汰されるのかもしれない。

文章として吐き出したら、こんな2017年もポジティブに生きられそう。

最近欲しいと感じたもの

駄文

最近の(少なくとも僕の知っている)Webフレームワークというか Web アプリケーションを作るためのエコシステム全体のバランスが崩れてあまり調和が取れていない気がする。FaaSとかを使うととっても安く全世界に公開できるシステムを作れるというのに、僕がそれをビビって本気で勉強する気が起きないのは、標準が無いからな気がするけど、それにしても面倒なことが多い。それぞれの単発の技術としては納得感があるのだけど、僕が Django とかで始めたときのような、ORM で M 書いて、テンプレートエンジンで V 書いて、正規表現とタプルで C 書いて、 mod_wsgi の設定書いて終わり!みたいな感じじゃないあたりが辛い。

URL とロジックの結びつけは、 zip アップロードして画面でポチポチ設定する気にならない。そこまで手間は変わってないからたぶん気分の問題なんだけど、なんとか統合なんちゃらとか、必要なステップのような気もするし、設定より規約に従ったら省けるステップのような気もする。 Swagger と zip をアップロードした後にあのあたりいじってるとうーんってなる。実はもっと簡単な方法があって僕がそれを知らないだけの話かもしれない。ちょっと気をつけて書いた Flask あたりを放り投げたら勝手に FaaS で実行してくれないかな。というかあのあたりは MVC それぞれの代替というよりも、これまでの Webサーバとかリバースプロキシ+C を 1 レイヤにした感じがする。そうなってくると、うまく開発スタイルを作るのが難しい。開発者がリバースプロキシを使うのもちょっとうーんってなる。エコシステムのバランスが取れていないような気もする。毎月無料分用意しとるやろって言われても、なんか開発が1台で完結できないのはモヤモヤする。クラウド上で動くアプリ作ってるんだからしゃーないやろって言われても、新幹線の中でノートパソコンを開いて遊んでいた時間は今後別なことに使わないといけなくなってしまう。そこまで困らないんだけどなんかモヤモヤする。

アカウント管理まわりはもう変わりきった感じする。数年前はクライアントサイドに保存してHMACで署名とかちょっと怖いなとか思ってたけど、最近はもう違和感ない。逆にスケールの観点からリクエストごとに同じ場所に問い合わせるとかやばいって気がする。保存先をクラスタにするってのもあるけど、 HMAC の良さには敵わない気がする。それで思ったのは HttpServletRequest のあたりとかもう不要だよなぁと。 Spark Java は最近触ってて好きなんだけど、やっぱり裏側に Servlet がチラチラと顔を出してくる。あぁやっぱり普遍的な抽象化って難しいなぁ。頼むからそんなに高く積み上げないでくれ。コントロールしたいのは些細なことなのに何層も掘り下げるのは残念な感じがする。

FaaS と Java は相性悪いって話もわかるんだど、 JavaScript でサーバサイド書くのはなかなか辛いものがある。最近の KVS だけならまぁいいんだけど、node.js + RDB で Promise まで含めたときの混沌とした感じはなんというかこれこそジャヴァスクリプトって感じがする。その点まぁPythonはいいぞ。でもやっぱりサーバサイドは Java バイトコードぐらいで動いて欲しいのと型はしっかりして欲しい。

検索エンジンミドルウェアも皆あれで満足しているんだろうか?ログ解析ツールとしてはよく聞くけど、プロダクトの部品として普通に検索エンジンとして使っている情報はあんまり見ない気がする。僕が知らないだけかもしれない。あのアップデートの辛さは聞く限りではそうとう辛い。検索と権限の組み合わせも考えるととても既存の何かではスマートに対処できる気がしない。権限は将来変わる可能性があるのでインデックスするときに用意できない。汎用的な検索サービスが欲しいけど、そのあたりを考えるとなかなかに難しい。

クライアントサイド周りも職場の席近い先輩が、サーバがどんどん状態放棄して複雑さが押し付けられてるって叫んでる。SPA の画期的なフレームワークもまだ無くて、 Angular2 には少し期待しているんだけど、大半の開発者が欲しいのは DI とかの裏方ではなくて、ヒストリ管理とかショートカットキーとかユーザに直接影響する部分ではないだろうか。近い気もするけどなんかここももやもやする。レスポンシブデザインも結構前から言われているけど、完璧に洗練される前に若干盛り下がった気がする。そしてなによりこうしていろいろ考えるとなんとかスクリプトコンパイルしてなんとかスクリプトとかなんとかシートにした後になんとかファイしてなんとかマップつくってってのがなんとかパックでできるらしいけど、俺はただそのコマンドにこのオプション付けて欲しいんだけどってのをなんとかプラグインのソースを探してなんとか修正して半日ぐらい終わるともう何かやり遂げた感じがする。ただコマンドのオプション1個足しただけなのに。このあたりはなんか太古の呪文があったような…、acとかinとかamとか、なんだ、うっ…頭が…。

あーなんかのうみそすきゃんしてぽんっとしてくれるそうちがほしい。

GNOME3用アプリケーション開発に入門してみる その3

GIO編。リファレンスをざっと見せよとのこと。

GIO Reference Manual: GIO Reference Manual

ファイルシステムにかかわるのは以下の6つ

  • GFile
  • GFileInfo
  • GFileEnumerator
  • GDrive
  • GVolume
  • GMount

GFileEnumerator はいわゆるイテレータ。 GDriveがGVolumeのリストを持っていて、マウントしていればGMountが使える。

読み書きのストリーム系はJavaと似ている。 確かにあのデコレータの設計は良いと思う。

あとシステムにインストールされているアプリケーションについては特別なクラスがある。 他にもソケット通信系、GSettings、D-Busなんかが用意してある。

なるほど。アプリケーションの裏側を作るには十分ってかんじだ。

_async が付いているメソッドは非同期で処理される。 終わったかどうかは _finish

GNOME3用アプリケーション開発に入門してみる その2

GObject

GObject Reference Manual: GObject Reference Manual

C言語オブジェクト指向を実現する仕組み。 他言語用にAPIを提供する仕組みも備えているので、 Cで書けばC++はもちろんPythonPHPとかからも使えるようになる。 たぶん逆もしかり。

ざっと見ではC++のvtableとかマングル名とかをCの構造体や命名規則、 マクロで実装している感じで合っていると思う。 加えて参照カウンタやObserverパターンのためのsignalの規則もあるっぽい。

チュートリアルから開始。

ヘッダファイルはハイフンかアンダースコアで区切るのが一般的っぽい。 privateを末尾につけた場合はインストールしない。

とりあえず maman-bar.h をコピペして、Object Construction, Object Destruction あたりまで進めてみる。

/*
 * Copyright/Licensing information.
 */

/* inclusion guard */
#ifndef __MAMAN_BAR_H__
#define __MAMAN_BAR_H__

#include <glib-object.h>
/*
 * Potentially, include other headers on which this header depends.
 */

/*
 * Type macros.
 */
#define MAMAN_TYPE_BAR                  (maman_bar_get_type ())
#define MAMAN_BAR(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_IS_BAR(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_BAR_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))

typedef struct _MamanBar        MamanBar;
typedef struct _MamanBarClass   MamanBarClass;
typedef struct _MamanBarPrivate MamanBarPrivate;

struct _MamanBar
{
  /* Parent instance structure */
  GObject parent_instance;

  /** Private data pointer */
  MamanBarPrivate* priv;

  /* instance members */
};

struct _MamanBarClass
{
  /* Parent class structure */
  GObjectClass parent_class;

  /* class members */
};

/* used by MAMAN_TYPE_BAR */
GType maman_bar_get_type (void);

/*
 * Method definitions.
 */

#endif /* __MAMAN_BAR_H__ */
/*
 * Copyright information
 */

#include "maman-bar.h"
#include <glib.h>
#include <glib/gprintf.h>

/* If you use Pimpls, include the private structure 
 * definition here. Some people create a maman-bar-private.h header
 * which is included by the maman-bar.c file and which contains the
 * definition for this private structure.
 */
struct _MamanBarPrivate
{
  GObject *an_object;

  gchar *a_string;
};

G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)

static void
maman_bar_dispose (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);
  g_printf("maman_bar_dispose\n");

  /* In dispose(), you are supposed to free all types referenced from this
   * object which might themselves hold a reference to self. Generally,
   * the most simple solution is to unref all members on which you own a 
   * reference.
   */

  /* dispose() might be called multiple times, so we must guard against
   * calling g_object_unref() on an invalid GObject by setting the member
   * NULL; g_clear_object() does this for us.
   */
  // g_clear_object (&self->priv->an_object);

  /* Always chain up to the parent class; there is no need to check if
   * the parent class implements the dispose() virtual function: it is
   * always guaranteed to do so
   */
  G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject);
}

static void
maman_bar_finalize (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);
  g_printf("maman_bar_finalize\n");

  g_free (self->priv->a_string);

  /* Always chain up to the parent class; as with dispose(), finalize()
   * is guaranteed to exist on the parent's class virtual function table
   */
  G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject);
}

static void
maman_bar_class_init (MamanBarClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  g_printf("maman_bar_class_init\n");

  gobject_class->dispose = maman_bar_dispose;
  gobject_class->finalize = maman_bar_finalize;
}

static void
maman_bar_init (MamanBar *self)
{
  self->priv = maman_bar_get_instance_private (self); 
  g_printf("maman_bar_init\n");

  self->priv->an_object = NULL; // g_object_new (MAMAN_TYPE_BAZ, NULL);
  self->priv->a_string = g_strdup ("Maman");
}

生成と破棄はたぶんこんな感じ。

#include "maman-bar.h"

int main(int argc, char const* argv[]) {
    GObject* bar = g_object_new (MAMAN_TYPE_BAR, NULL);
    g_object_unref(bar);
    return 0;
}

破棄がdisposeとfinalizeで分かれているのは参照カウンタがループしている時のためっぽい。

GNOME3用アプリケーション開発に入門してみる

このへんから情報を取ってきたらよさそう。

GNOME Developer Center

PythonとかC++とかValaとか使った方が効率的そうだけど、最初ぐらいCでやるか。

Getting started with writing a GLib/GTK+ application in C

  1. GLib core
  2. GObject
  3. GIO
  4. GTK+

の順でやれとのこと。

GLib

先程のリンクから PDF へ The GLib/GTK+ Development Platform

リファレンスはこちら GLib Reference Manual: GLib Reference Manual

まずは簡単なマクロ

printf("%d\n", MAX(2, 3));
printf("%d\n", MIN(2, 3));
printf("%d\n", CLAMP(5, 10, 20));

コンパイルはこんな感じで

gcc $(pkg-config --cflags glib-2.0) -o main 01_glib_core.c $(pkg-config --libs glib-2.0)

あとはデバッグ用のマクロ

gint f(gint x) {
    g_return_val_if_fail(x != 0, 0);
    return 100 / x;
}

この関数に 0 を渡すと ** (process:31444): CRITICAL **: f: assertion 'x != 0' failed のように表示される。 リリース版を作る時は -DG_DISABLE_CHECKS を付けてコンパイルすればチェックされない。

お次はメモリ管理系。 g_malloc 関数等が存在するが、通常は g_new で書くっぽい。 文字列用にもいくつかある。

データ構造は必要になった時でいいや。

PythonでMACDを計算する

MACD (Moving Average Convergence Divergence) | FX・証券取引のマネーパートナーズ -外為を誠実に-

このあたりを参考に、EMAはこんなかんじ。

def ema(l, t):
    result = []
    for p in l:
        i = len(result)
        if i < t: # t日目までは単純平均
            result += [float(sum(result) + p) / (i + 1)]
        else:
            last = result[-1]
            result += [last + 2. * (p - last) / (t + 1)]
    return result

あとは式通り。

ema12 = np.array(ema(prices, 12))
ema24 = np.array(ema(prices, 24))
macd = ema12 - ema24
signal = np.array(ema(macd, 9))

matplotlibで描画してみる。

x = np.arange(0, len(dates))
plt.figure(figsize=(150, 4)) # サイズは適当に調整
plt.xticks(x, dates[::-1])
plt.plot(x, macd)
plt.plot(x, signal)

ipython notebookとか使うと便利。