白猫のメモ帳

JavaとかC#とかJavaScriptとかHTMLとか機械学習とか。

排他的論理和は^じゃなくて!=でよくない?

こんにちは。
ほんとに、ほんとーに毎日毎日暑いですね。
もうとろけてしまう。

で、なんだか偉い人に怒られてしまいそうなタイトルですが、
論理演算子を条件演算にしか使わないような我々には、
滅多に現れない排他的論理和をググりながら書くよりはいいんじゃないのってお話。

論理演算の種類

論理演算の種類はたくさんあるのですが、実際プログラミングで利用するものはある程度限られています。

論理積(AND)

条件Pと条件Qがあるとき、PとQの両方が真であることを論理積と呼びます。
(true、falseって書いたら読みづらかったので、○×にしますね。)

条件P 条件Q AND
× ×
× ×
× × ×

一般的にプログラミング言語では記号「&」を利用して、

p & q

のように記述します。

また、条件演算に利用する場合には、左から評価するとすれば、
条件Pがfalseの場合には条件Qの値にかかわらずfalseとなるため、短絡評価(ショートサーキット)することができます。
これは一般的にプログラミング言語では記号「&」を二つ重ねて、

p && q // pがfalseの場合、qの評価はしない

のように記述します。
今回の記事では深くはつっこみませんが、パフォーマンスの観点や副作用の観点から、一般的には短絡評価を使うことが多いです。

否定論理積(NAND)

条件Pと条件Qがあるとき、PとQの少なくとも片方が偽であることを否定論理積と呼びます。

条件P 条件Q NAND
×
×
×
× ×

論理積(AND)の反転であることから、一般的にプログラミング言語では否定「!」を利用して、

!(p && q)

のように記述します。

論理和(OR)

条件Pと条件Qがあるとき、PとQの少なくとも片方が真であることを論理和と呼びます。

条件P 条件Q AND
×
×
× × ×

一般的にプログラミング言語では記号「|」を利用して、

p | q

のように記述します。

また、論理積と同様に、条件Pがtrueの場合には条件Qの値にかかわらずtrueとなるため、短絡評価することができます。

p || q // pがtrueの場合、qの評価はしない

こういうことですね。

否定論理和(NOR)

条件Pと条件Qがあるとき、PとQの両方が偽であることを否定論理和と呼びます。

条件P 条件Q AND
×
× ×
× ×
× ×

論理和(OR)の反転であることから、一般的にプログラミング言語では否定「!」を利用して、

!(p || q)

のように記述します。

排他的論理和(XOR)

条件Pと条件Qがあるとき、PとQどちらか片方が真で、もう片方が偽であることを排他的論理和と呼びます。

条件P 条件Q AND
×
×
×
× × ×

一般的にプログラミング言語では記号「^」を利用して、

p ^ q

のように記述します。
Excelの式やVB系では「^」はべき乗の意味で利用されるので注意)

また、条件Pの値が決まっても条件Qの値が決まらないと判定できないため、短絡評価はありません。

定排他的論理和 (XNOR)

条件Pと条件Qがあるとき、PとQ双方が真または偽であることを否定排他的論理和と呼びます。

条件P 条件Q AND
× ×
× ×
× ×

一般的にプログラミング言語では記号「^」を利用して、

!(p ^ q)

のように記述…するんですかね?あんまりしない気もしますね。

XORとかXNORって使う?

要するにAND、OR、XORとその反転(否定)があるよって話なのですが、
せっかく演算子まで用意してくれてますけど、「^」ってコード上で見ることあんまりないですよね。

めったに使う場面がないのだから、使えるタイミングでは積極的に使っていこう!っていうのもいいのですが、
自分は分かっても他の人的には混乱するかも?って思うと使いにくいのですよね。

で、そもそもの話、XORの「PとQどちらか片方が真で、もう片方が偽である」
っていうのはPとQの結果が一致していない、つまり、

p != q

なんですよね。

同じように、XNORの「PとQ双方が真または偽である」
っていうのはPとQの結果が一致している、つまり、

p == q

ってこと。

なんかこっちのほうが見慣れてるからいいかなって思うのです。

まぁ、「ここは排他的論理和が正しくない?」とかいったらかっこいいのかもしれないですけどね。
ちなみに「排他的論理積」なんて言葉はないですよ。ですよー。

JavaScriptでメソッドをイベントバインドするとthisは何を指すの?

こんにちは。

ワールドカップが始まりましたね。
3時からとかだといっそ諦めがつくのですが、
0時くらいから始まる試合とかをつい見てしまって翌日ねむねむになる気がしてなりません。

さて、この前JavaScriptを書いていてふと思ったこと。
表題の通りです。

先に結論を書いてしまえば、イベントが発生したDOMになります。

JavaScriptのthisの指すものの種類はいろいろとあるのですが、
今回の目的はそれを解説することではないので、話題にする2つだけまず確認しましょう。

メソッドが指すthis

JavaScriptに限った話ではないですが、
わりとあいまいに使われている「関数」と「メソッド」は実際の挙動としては明確に区別されます。
Javaとかのオブジェクト指向言語だと関数はstaticメソッドとか呼ばれますね)

簡単にいえばメソッドとはオブジェクトに属する「メンバ関数」のことです。
なので、基本的にはオブジェクトに対する操作を定義した手続きなのですが、
オブジェクトのメンバにまったく関係しない、参照透過性のある関数を定義することができないわけではありません。

おっと、ちょっと話がそれましたね。
つまり、こんな感じのfunctionの定義はメソッドです。

var obj = {};
obj.method = function() {
    alert("hoge");
}

もしくはこんなのとか。

var obj = {
    method: function() {
        alert("hoge");
    }
};

で、このメソッドの中でthisが何を指すかというと、「自身が属しているオブジェクト」です。

var obj = {
    value: "hoge",
    method: function() {
        alert(this.value);
    }
};
obj.method();  // hoge

こんな感じですね。ほかの言語でも大体同じなんじゃないでしょうか。

イベントバインドした関数が指すthis

次にイベントバインドについてみていきましょう。

クライアントサイドのJavaScriptを考えた場合、画面初期表示時に様々な処理を行うほかに、
ユーザが「ある要素をクリックした」とか「マウスカーソルを動かした」とか「キーボードで何か入力した」
といった様々なイベントが発生します。

これらのイベントが発生した際に、なにかしらの処理をさせたい場合、
イベントに処理を「バインド」してあげる必要があります。

document.getElementById("hoge").addEventListener("click", function() {
    alert("hogeをクリックしたよ!");
});

jQuery的で書くとこんな感じ。

$("#hoge").on("click", function() {
    alert("hogeをクリックしたよ!");
});

で、この関数の中でthisが何を指すかというと、「イベントが発生したDOM」です。

<input type="text" id="hoge" value="fuga" />

document.getElementById("hoge").addEventListener("click", function() {
    alert(this.value);
});
// クリックするとfugaがアラートされる(inputクリックしたらアラートとかどういうこと)

メソッドをイベントバインドした場合のthis

やっと本題。

これら2つって実は共存することができます。
つまりどういうことかというと、

<input type="text" id="hoge" value="fuga" />

var obj = {
    value: "hoge",
    method: function() {
        alert(this.value);
    }
};
document.getElementById("hoge").addEventListener("click", obj.method);
// クリックするとfugaがアラートされる

この場合、「this.value」が指すのは

・「obj」のメンバ変数である「value」の値である「hoge
・イベントが発生したinputが持つ値「fuga」

どっちなのでしょうか。

正解は、イベントが発生したinputが持つ値「fuga」です。

じゃあこんな風にinputが持たない属性の「val」とかにしてみると使えるのかというと、
あくまでinputから「val」属性を探しに行って、結果は「undefined」になります。

var obj = {
    val: "hoge",
    method: function() {
        alert(this.val);
    }
};
document.getElementById("hoge").addEventListener("click", obj.method);
// クリックするとundefinedがアラートされる

オブジェクトのメンバを参照することはできないので残念ですね。
で終わってもいいのですが、せっかくなので回避方法を検討します。

var obj = {
    val: "hoge",
    method: function() {
        var self = this;
        return function() {
            alert(self.val);
        };
    }
};
document.getElementById("hoge").addEventListener("click", obj.method());
// クリックするとhogeがアラートされる

こんな感じでオブジェクトのthisを囲い込んだクロージャをバインドしたりするとなんとかなったりしますね。

使いどころがそんなにあるかは謎ですが、覚えておいて損はないかな。

fastTextでニュースをカテゴリごとに分類する

こんばんは。

暑かったり暑くなかったり、晴れだったり雨だったり。
日によって全然気候が違いますね。関東もそろそろ梅雨入りでしょうか。

さて、fastTextによる単語のベクトル表現を試してからまたずいぶんと間が空いてしまいましたが、
今回は分類をやってみようかと思います。

分類するものがないんだよなーとか思っていたんですが、
そういえばだいぶ前にベイジアンフィルタでニュースの分類したときのデータが
どこかに残っていたような気がするな、と思って探してみたら発見できたのでこれを使います。

shironeko.hateblo.jp

前処理

fastTextに分類してもらうためには書式を変換してあげる必要があります。

学習データが

__label__【ラベル】, 【半角スペースで分かち書きした文】

という書式。

__label__IT・科学, アップル iPhone 不正 ユーザー 指紋 収集 特許 出願

こんな感じ。
前の記事見てもらうとわかるかもしれませんが、名詞しか抜き出していないのでそのまま使います。
ちなみに「__label__」の部分は引数の設定で変更することもできます。

で、分類データが

【半角スペースで分かち書きした文】

という書式。こっちはただの分かち書きだけ。

国内 映画 ランキング 君の名は。 会心 V スタート 後妻業 女 4 位 タートルズ 10 位

こんな感じ。
2年近く前のニュースなので、なんだか懐かしい。

学習

前処理が終わったら学習モデルを作ります。

# /fastText/fasttext supervised -input learn.txt -output model -epoch 1000

エポック数だけ1000にしてみましたが、それ以外はデフォルトです。

Read 0M words
Number of words:  4051
Number of labels: 5
Progress: 100.0% words/sec/thread:  350035 lr:  0.000000 loss:  0.263343 ETA:   0h 0m

こんな感じの表示が出て、2秒くらいで終わりました。はやーい。
まぁ、コーパス数800なのでこんなもんですかね。

分類

あっという間に学習が終わったので、分類してみます。

/fastText/fasttext predict-prob model.bin predict.txt 3

ほんとに一瞬で終わります。

__label__エンタメ, 0.999987
__label__IT・科学, 0.99884
__label__エンタメ, 0.999866
__label__スポーツ, 0.999957
__label__エンタメ, 0.999686
__label__経済, 0.999839
__label__エンタメ, 0.99961
__label__エンタメ, 0.999815
__label__スポーツ, 1
__label__経済, 0.999296

あれ、なんかラベルがちょっとイメージと違うけどまぁ分類はできているんでしょう。たぶん。

結果

○__label__スポーツ, 0.999846 大江香織、藤本麻子が“破格”の韓国ツアー出場)
○__label__IT・科学, 0.999927 「ねこ休み美術館」
○__label__スポーツ, 0.999587 【MLB】3Aでストライク率70% ロッテ戦力外の中後、11戦無失点で防御率0.00継続
○__label__スポーツ, 0.999922 元時天空 髪は失っても親方で「成長したい」
○__label__スポーツ, 0.999848 熾烈な優勝争い続くパ ソフトバンク&日本ハム、カギ握る残りの対戦は?
○__label__エンタメ, 0.999742 【ディズニー】ジェラトーニが街中に涼しげアート!期間限定夏デコレーション
○__label__ライフ, 0.9997 医師が考える。新しいタバコ「iQOS(アイコス)」は健康的なのか?
○__label__エンタメ, 0.999801 「ブラクロ」がジャンプのアニフェスでアニメに!参加受付もスタート
○__label__エンタメ, 0.999793 俳優イ・サンヨプ、コン・ヒョンジュと破局後の近況報告
○__label__スポーツ, 0.999718 フットゴルフ日本代表、第1回アジアカップで上位独占 初代アジア王者に

おお、いきなり100%だ。

×__label__エンタメ, 0.999997 伝説の映画「バトルシップ」 まさかの極上爆音上映が決定!
○__label__経済, 0.706788 エコ運転教習のファインモータースクール、エコドライブ全国大会で3年連続表彰台
×__label__エンタメ, 0.94055 アトピー性皮膚炎ってどんな病気? 乳児湿疹とアトピー性皮膚炎の違いとは?
○__label__スポーツ, 0.997004 バルサ、29日中にもP・アルカセル獲得を発表へ すでにメディカルチェックをパス
×__label__IT・科学, 0.742081 拡張現実開発プラットフォームの新バージョンをリリース
×__label__エンタメ, 0.815593 【鈴鹿8耐】あの感動をもう一度、公式ブルーレイ&DVD 917日発売
○__label__経済, 0.889665 「電力事業者」の新設法人数が初の減少、「太陽光」が4割減
○__label__エンタメ, 0.981648 まゆゆが舞妓さんに! メロメロの豊川悦司「ファンクラブに入りたい」
○__label__スポーツ, 0.939998 広島松山8号2ラン「自分のスイングできました」
○__label__スポーツ, 0.764349 3基のパワーユニットを確保したハミルトン、今後はアップグレードの恩恵得られず

とおもったら6割。安定しませんね。

○__label__IT・科学, 0.922675 東大、「水」ベースのリチウムイオン伝導性液体を発見
○__label__経済, 0.715266 セダンのトランクに積める折りたたみ自転車、あさひが発売
×__label__スポーツ, 0.882106 個人間カーシェアのエニカ、1周年記念イベント 917日
○__label__スポーツ, 0.950249 田口 調整に自信「世界戦では割といい方」
×__label__エンタメ, 0.634755 怖いと思う災害1位は地震、「住んでいる地域・家は危険だと思う」32.7%、保険クリニック調べ
○__label__ライフ, 0.999923 【高校受験2017】大阪府公立高、体験入学や説明会一覧…茨木11/9・北野10/8
×__label__経済, 1.00001 都市開発:5 とび職 正確な鉄骨組み、段取り勝負
○__label__エンタメ, 0.804691 俳優イ・サンヨプ、コン・ヒョンジュと破局後の近況報告
○__label__スポーツ, 0.999977 インテルデビュー戦を白星で飾れなかった伊代表MF「勝つためにここへ来たから残念」)
○__label__エンタメ, 0.42318 エースコック、主力商品のスーパーカップ1・5倍シリーズをリニューアル

7割。やっぱり学習データが足りていなさそうですね。

まとめ

fastとつくだけあってとても処理が速いし、使い方もとてもわかりやすいです。
しっかりと分類するためにはデータの量がもっと必要かとは思いますが、
その実力の片鱗くらいは見ることができたかなという感じです。

そのうちにもっと分類に適したデータを集めることができたら、また試してみたいですね。
それでは。