タイトルって難しい。

学力も体力もない人間の雑記帳。

Japan.R 2016にてLTをしました #JapanR

3ヶ月以上前の話ですが、Japan.RにてLTをしました。
なぜに今頃かといいますと、思い出したからという感じです。

Japan.Rとは

日本各地で統計処理ソフトウェアである R に関する勉強会が行われています。 Fukuoka.R、 HiRosima.R(HijiyamaR)、 Kashiwa.R、 Kobe.R、 Nagoya.R、 Okinawa.R(沖縄 R 同好会)、 Osaka.R、 SappoRo.R、 Shiga.R、 Tokyo.R、 Tsukuba.R、 Yamadai.R、 Yokohama.R というように日本各地で開催されています。これらの勉強会の主催者や参加者が年に一度集まって開催されるイベントが Japan.R です。

(Japan.RのHPより)

去年は副主催とかいう謎の立ち位置の僕でしたが、今年は何してたのかというと、運営の人の邪魔にならない程度に寝てました(嘘)。

can.hatenadiary.com

何を発表したのか

LINE。みなさん使ってると思います。使ってない人は…まあいるとは思いますが、今回はそれは置いといて。
LINEに解析結果とかそもそも解析終わったよみたいなのを飛ばせたら最高ですよね。ってことでそれをしてくれる野良パッケージを作りましたよって話です。

パッケージ作り裏話

私は学校の同期とかと比較してもめちゃくちゃ意識が低いので、最近よくみかけるなければつくるそれが(以下略)の方々ほど強い意志はなかったのですが、とりあえず直近で必要になったから作ったという感じです*1
それだけ急を要してたという割には、Japan.Rがはじまった時間から作り始めて、LTの手前に作り上げるという謎の縛りルールを適用しました。
ゲームとかでもそうですけど、縛りルールはスリルを味わえるのでおすすめです。
あと、Rのパッケージをつくるのは実は今回が初めてだったので、コンパイル周りで手間取った気がします。肝心のRのコード自体は割と楽にかけたと言うね。
LINE Notify自体は、所定のAPIを叩けば問題なく出来ます。個人的にはUNIX環境ならcurlでやるのがオススメですが…笑。

スライド

LINE Notifyの今後

github.com

とりあえず画像送信とか対応したいです。あとエンコード周りが悲惨なんで日本語対応にさせたいです。
あとReadmeはきちんと書きたいです。
そんな感じです。

今後

Tokyo.Rには学部4年から参加していますが、この3年間で色々お世話になったので、貢献したいと考えています。
何するかはきめてませんが…。

パーフェクトR

パーフェクトR

Rによるデータサイエンス(第2版) データ解析の基礎から最新手法まで

Rによるデータサイエンス(第2版) データ解析の基礎から最新手法まで

R言語徹底解説

R言語徹底解説

イケてる大人 イケてない大人 シニア市場から「新大人市場」へ (光文社新書)

イケてる大人 イケてない大人 シニア市場から「新大人市場」へ (光文社新書)

*1:別に某団体?を批判しているわけではありませんのであしからず

意識の低い学生が書く就職活動のあれこれ

どうも、私です。
就職活動が明日から解禁だそうなので、知らなくてもいいけど、知っててもいいかもしれないことだけ書いていきます。
色々やることあるんですが、現実逃避の記事です。

先に簡単に経歴を書きますと、2015年に修士課程に入学し、2017年に修了&入社予定で、推薦は一切使いませんでした。
僕の所属する研究科・専攻は比較的、メーカーにいくか、IT系にいくかが大半なので、推薦のリクルーター面接なり、コーディング試験なりで失敗しないようにした方がいいかもしれません。

説明会解禁以降(3月以降)

合同説明会

色々な会社がそれぞれのブースで簡単に会社説明するやつです。
興味ある会社があると行ってみたら良いと思いますが、学生が興味持つ会社っていうとどうしても知ってる企業になりがちなので、混み合います。
冗談抜きで混み合います。

私は学内のやつだけいきました。某コミケ会場とかでも行われてたりしますけど、よほどの強い意志がない限り交通費が無駄な気がします。
あと、秋葉原で開かれてた大学限定のやつも1日だけ覗きました。まあ行った理由は、合説ではなく、Amazonギフt…ゲフンゲフン。
服装は、一応スーツで行きました。よくわからん時はスーツ安定。

人混みが苦手な私にとっては、合説は苦行でしかなかったので、よほど興味のある会社やノベルティグッズが良い会社じゃない限りはあえて人気のないブース(自分以外誰も居ないブース)を中心に回ってました。
そういうブースって1対1なんで、色々教えてくれたりします。正直、この時に教えてもらったことが結構後に響いてきたりしたんで…。

マイページ登録

3/1の午前0時になると、リク○ビとかマ○ナビとかと同じく解禁するやつです。
正直、なぜみんな0時になって必死にアクセスするのかよくわかりません。
基本的には、個別の企業ごとに自分で登録するか、合説とかで貰う紙に書いたら登録してくれたりします。
まあみんな必死になりますけど、焦んなってって話です。

企業説明会

マイページに登録したら一覧となって出てきます。
ここでは、業界ごとにスタンプラリーと言われたりするところもあるそうです。大変だなあ。
ここで意識の高い学生は、頑張って質問したり、質問時に「○○大学○○学部○○ゼミ(または研究室)所属の〜〜です」とか言ってたりします。都市伝説だと思ったらほんとにいました。聞いてる側もうんざりするのでやめたほうが良いかもです。ただ、聞きたいことを聞いてくれた時は助かりますが。

大学毎の説明会とか、大学関係なしのやつとか色々あります。
自分のスケジュールと照らし合わせて考えたら良いでしょう。

ちなみに私は、興味のある会社となんかプレゼント貰えるという噂を聞いたところを行きました。どんだけ意識低いんだ。

面接

気づいたら始まってます。急に電話きてOBと会うパターンはリクルーター面接ってやつです。
なので、失礼のないようにしましょう。
よくある質問は、「志望動機(会社そのものと業界全体)」、「強み弱み」あたりでしょうか。
面接対策本読むくらいならば、ワ○キャリアとか外資○活ドットコムに載ってるような(信頼できるか不明な)体験談読んでる方がまだましです。

悲しいことに落ちる時は落ちます。落ちない時はびっくりするくらい話がスムーズに進みます。

エントリーシートWebテスト・テストセンター

エントリーシートは、質問に対してきちんと答えたらまずまず大丈夫です。
あと一発勝負で書かないで、書いた後見直したら良いでしょうとしか。
昔、友人のESを見たことあるのですが、とにかく誤字脱字変換ミス、文法的な誤りがあって、読むのがしんどかった記憶があります。
あとは社会的にNGなこと書かなければ、大丈夫かと。

Webテストとテストセンターはせっかく参考書買ったのに、問題形式の確認で読んだくらいでした。業界によっては高い水準が求められるそうです。

その他

イベント(説明会や面接など)をハシゴしてしまうときもあると思います。都内ならば、東京メトロの24時間乗車券とか便利です。
これは、最初に改札通してから24時間後までならば、改札通すと乗り放題です。23時間59分経過した時に改札通しても大丈夫です(今後仕様が変わるかもしれません)。
正直、この記事で一番有用なのはここだけだと思います。

最後に

一切会社名や具体的な話は触れずに書こうと思うと、これくらいしか書けません。
初稿の段階では書き忘れてたのですが、就職偏差値とか就職難易度はあんまりあてにしないほうが良いです。あれ、出してる人は全社受けたわけじゃないんでしょ?いちいち気にしてるような人は自分の意思決定すら自分でできないのかなって思ったりします。
そういうの気にしてる暇あったら、美味しいご飯食べるなり寝るなりした方がいいです。

個別に相談の場合は、知ってる後輩ならばできる範囲でのります・・・たぶん。

就職四季報2018年版

就職四季報2018年版

これが本当のSPI3テストセンターだ! 【2018年度版】

これが本当のSPI3テストセンターだ! 【2018年度版】

2018最新版 史上最強SPI&テストセンター超実戦問題集

2018最新版 史上最強SPI&テストセンター超実戦問題集

【主要3方式〈テストセンター・ペーパー・WEBテスティング〉対応】これが本当のSPI3だ! 【2018年度版】

【主要3方式〈テストセンター・ペーパー・WEBテスティング〉対応】これが本当のSPI3だ! 【2018年度版】

よくあるQ&A

Q: OB訪問した?
A: 知り合いの先輩または電話かかってきたリクルーター以外は話聞いてないです

Q: 何社受けた?
A: 覚えてる限りだと1桁くらいです(ES出したのが)

Q: 学部の時は就活した?
A: 大学院進学決めちゃってたくらい意識が低いのでしてるわけがないです

Q: 外資受けた?
A: 国内より選考が早いのと、就活生が意識高い系なのかほんとに意識高い人なのか知りたくて少し受けました

Q: 面接落ちたことある?
A: そりゃあるけど、あくまでその時の自分とは縁がなかったのだと今では考えています

Q: もう1回就活したい?
A: どちらでもないです

【R Advent Calendar 2016】Hydrogenはいいぞ

みなさんいかがお過ごしでしょうか。私は最近色々辛かったです。
楽しい日々って有限なんだなと思います。
さて、この記事は「R Advent Calendar 2016」15日目の記事です。

qiita.com

はじめに

先日、水素水を買いました。高かったです。
おいしかったです。また飲みたいです。

Hydrogen

Hydrogenとは、Atom上でREPLできる素晴らしいパッケージです。
仕組みとしては、表向きはAtomですが、裏でJupyter Notebookを動かしているという感じです。 私は、Pythonでごにょごにょするときは基本Hydrogenを使っていたのですが、最近はRを書く際にもその波が…。

インストール方法

JupyterとIRKernelの導入

僕はPython3派なのですが、hydrogenのビルドを行う際にはPython2系が必要なので2系も導入します。
Pyenvがインストールされていることを前提として、Pythonのインストール例を示します。

まずPython3系の環境構築を行います(pipのバージョンは違うかもしれません)。

Youchan@Sunshine_Macbook ~ $ pyenv install 3.5.2
Youchan@Sunshine_Macbook ~ $ pyenv global 3.5.2
Youchan@Sunshine_Macbook ~ $ pip -V
pip 9.0.1 from /Users/Youchan/.pyenv/versions/3.5.2/lib/python3.5/site-packages (python 3.5)
Youchan@Sunshine_Macbook ~ $ pip install jupyter

次にRStudioを起動し、以下を実行します。

install.packages(c('repr', 'IRdisplay', 'evaluate', 'crayon', 'pbdZMQ', 'devtools', 'uuid', 'digest'))
devtools::install_github('IRkernel/IRkernel')

「ターミナル上でRを開いて」以下を入力し、実行します。

Youchan@Sunshine_Macbook ~ $ R
(以下略)
'q()' と入力すれば R を終了します。

>IRkernel::installspec()

これでJupyter NotebookでのIRKernelの導入が完了しました。 試しに

Youchan@Sunshine_Macbook ~ $ jupyter notebook

と入力し、Jupyterを起動すると以下のようになっているはずです。

f:id:cancolle:20161214163922p:plain

Hydrogenのインストール

Python2系の環境構築を行います。

Youchan@Sunshine_Macbook ~ $ pyenv install 2.7.12
Youchan@Sunshine_Macbook ~ $ pyenv global 2.7.12
Youchan@Sunshine_Macbook ~ $ pip -V
pip 8.1.1 from /Users/Youchan/.pyenv/versions/2.7.12/lib/python2.7/site-packages (python 2.7)
Youchan@Sunshine_Macbook ~ $ pip install jupyter

これでPython2系に切り替わりました。

Youchan@Sunshine_Macbook ~ $ apm install hydrogen
Youchan@Sunshine_Macbook ~ $ apm install language-r
Youchan@Sunshine_Macbook ~ $ pyenv global 3.5.2

次にkernelspecの情報を取得します。

Youchan@Sunshine_Macbook ~ $ jupyter kernelspec list --json
{
  "kernelspecs": {
    "python3": {
    (以下略)
    }
  }
}

この{}内を全てコピーしてください。
Atomを起動し、Preferences -> Packages -> hydrogen -> Settings を開きます。 f:id:cancolle:20161214173030p:plain

Kernel Specsのところに先程コピーした内容をペーストします。

f:id:cancolle:20161214173042p:plain

これで完全に準備完了です。

実際にやってみた

Atomを起動します。
右下の「Plain Text」をクリックし、Rと入力してEnter。
Rのコードを入力します。
実行したい部分を選択し、 Cmd(Ctrl) + Enterで実行。
f:id:cancolle:20161214171604p:plain

どうでしょうか?Atomを使うことでトライアンドエラーを繰り返しながら、イケてるデータ分析ができます。
RStudio、最近起動しなくなってごめん。

おわりに

Hydrogenはいいぞ。

Atom実践入門──進化し続けるハッカブルなエディタ (WEB+DB PRESS plus)

Atom実践入門──進化し続けるハッカブルなエディタ (WEB+DB PRESS plus)

改訂2版 データサイエンティスト養成読本 さくっとレビュー

はじめに

これは技術書献本大感謝 Advent Calendar 2016 9日目の記事です。

qiita.com

改訂2版 データサイエンティスト養成読本をご恵贈いただきました。ありがとうございます。保存用、観賞用、布教用のうちの観賞用として使用しています。
今後ともよろしくお願いします。

改訂2版 データサイエンティスト養成読本 [プロになるためのデータ分析力が身につく! ] (Software Design plus)

改訂2版 データサイエンティスト養成読本 [プロになるためのデータ分析力が身につく! ] (Software Design plus)

内容

巻頭企画:データサイエンティストの仕事術
 第1章:データサイエンティストに必要なスキル
 第2章:データサイエンスのプロセス
 第3章:「ビッグデータインフラ」入門

特集1:データ分析実践入門
 第1章:Rで統計解析をはじめよう
 第2章:RStudioでらくらくデータ分析
 第3章:Pythonによる機械学習
 第4章:データマイニングに必要な11のアルゴリズム

特集2:マーケティング分析本格入門
 第1章:Rによるマーケティング分析
 第2章:mixiにおける大規模データマイニング事例
 第3章:ソーシャルメディアネットワーク分析

特別記事:Fluentd入門

特別企画:データ分析のためにこれだけは覚えておきたい基礎知識
 第1章:SQL入門
 第2章:Webスクレイピング入門
 第3章:Tableau実践入門

さくっと評価

良い点

ある程度プログラムを書いたことがある人ならば、データ分析に関連する「〜したい!」という目的を達成する際に良い道標となると思います。
また、本書は比較的「浅く広く」という内容であり、「深く狭く」ということを求めている人には不向きかと思われます。
加えて、ある程度データ分析に携わってらっしゃる方から見ても、新しい発見を得られるのではないかと思います。私自身、データ分析を生業としている人間ではないですが、「なるほど、これに〜が使えるな!」とか思うことが多かったです。さらに、実際にサンプルのコードが記載されていること、そして(実際に運用で使われる際に)必要十分な説明がなされていることも良い点だと思います。
また類書にはない、Tableau入門や、Webスクレイピング入門など幅広く扱っている点も良いところかと思います。幅広いとはこのことを言うのでしょう。

うーんな点

正直、エンジニアだとか、データ分析またはプログラムを書いたことない人には辛すぎるかなという感じがします。
対象読者層の範囲外だから仕方ないといえばそうかもしれませんが、「とりあえず今からデータサイエンティストになるぞ!(宣言)」な方には辛いかなと思います。
それぞれのツールや統計的手法についてもう少し基礎的な面から理解するには別書が必要かと思います。
今後、初心者向けに何かの本があれば、その次に読むべき本として紹介できるかと。(そういう本が出ることを期待して)

おすすめのところ

特集1のデータ分析実践入門です。データマイニングに必要なアルゴリズムを網羅しているだけでなく、本書では珍しくPythonを使った機械学習をしてみたり…(基本的に本書では、Rでのデータ分析がメインだと思います)。
まだ学生ということもありその目線で書きますと、学生でまだデータ分析の理論の一部を習っただけの方、もしくは全く何も知らないという方にぜひ読んで欲しい部分かと思います。もちろん、これだけが全てではないですが、何をすべきか、何を勉強するとよいかのヒントが得られると思います。

最後に

みなさん是非買いましょう。え?まだだって?
下のリンククリックすれば買えますよ!!

改訂2版 データサイエンティスト養成読本 [プロになるためのデータ分析力が身につく! ] (Software Design plus)

改訂2版 データサイエンティスト養成読本 [プロになるためのデータ分析力が身につく! ] (Software Design plus)

今回はさくっと書評しましたが、〜のファッションチェック並の書き方でも良いかななんて思いました。
また献本してくださる優しい方がいらっしゃるといいですね…。

データサイエンスLT祭り 2夜目 にて発表を行いました(報告)

お久しぶりです。最近は研究室にてずっと作業をしています。
さて、データサイエンスLT祭りというイベントがありまして、そちらで発表しました。
発表内容は、マッチングアルゴリズムについてで、この内容に興味を持ったのは、たまたま実験を回しているときに適当に読んでいた論文の1つに、今から紹介するマッチングアルゴリズムをとある着眼点から応用したもので、面白かったためです。
そちらの論文の内容については今回の話とは無関係なので割愛しますが、実際に手を動かしながら理解するのはやっぱり楽しいなあと思った次第です。

スライドは↓です。ネタ要素が強いですが、実際のアルゴリズムの流れあたりは(僕の割には)頑張った方(?)なので、ぜひ。

【C++】配列とVectorとArrayで比較

きっかけ

以前、C++で実装した際に、コードを読まれた方からなんでVectorにしないの?と聞かれたことがありました。
機能面での違いはたしかにありますが、固定サイズならば別に配列でもOKではと思っていたのですが、ふと気になったので調べてみました。

比較対象

比較した方法は次の4通りです。

  • 配列(一番最初に習うであろうもの)
  • Vector(配列っぽく)
  • Vector(push_back)
  • Array(C++11から追加されたもの)

Vector同士で比較しているのは、配列っぽく使うパターンと、push_backで代入させた場合のものの2種類です。
push_backは遅いと書いていらっしゃる方もいたので、比較として入れてみようと思い、含めました。

コード

ダメダメながらも書いたコードは次に続きます。
やったことはすごく単純で、10万のデータを作って、そのデータから総和を求めるという操作です。
もっと良いベンチマークがあるかもしれませんが…。

配列(一番最初に習うであろうもの)

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  long int a[MAX+1];
  // Array
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    a[i] = i;
  }
  long int sum1 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum1 += a[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

↑の修正版

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  long int a[MAX+1] ={};
  // Array
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    a[i] = i;
  }
  long int sum1 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum1 += a[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

Vector(配列っぽく)

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  std::vector<long int> b1(MAX);

  // vector(like Array)
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    b1[i] = i;
  }
  long int sum2 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum2 += b1[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

Vector(push_back)

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  std::vector<long int> b2;
  // vector(push_back)
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    b2.push_back(i);
  }
  long int sum3 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum3 += b2[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

Array(C++11から追加されたもの)

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  std::array<long int, MAX> c;
  // C++11's Array
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    c[i] = i;
  }
  long int sum4 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum4 += c[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

↑の修正版

#include <iostream>
#include <cstdio>
#include <vector>
#include <array>
#include <chrono>

int main(int argc, char const *argv[]) {
  std::chrono::system_clock::time_point start, end;
  double elapsed;
  const long int MAX = 100000;
  std::array<long int, MAX> c = {};
  // C++11's Array
  start = std::chrono::system_clock::now();
  for (long int i = 0; i <= MAX; i++) {
    c[i] = i;
  }
  long int sum4 = 0;
  for (long int i = 0; i <= MAX; i++) {
    sum4 += c[i];
  }
  end = std::chrono::system_clock::now();
  elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
  std::cout << elapsed << "μs" << std::endl;
  return 0;
}

結果

単位はすべて、μsことマイクロ秒(100万分の1秒)
rev2とついてるものは修正版です。

Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./array.out
792μs
Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./array_rev2.out
489μs
Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./vector_like_array.out
603μs
Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./vector_push_back.out
2962μs
Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./array_cpp11.out
827μs
Ruby@Kotori-no-MacBook-Pro ~/Desktop $ ./array_cpp11_rev2.out
528μs

やっぱりpush_backは遅いですね。
Vectorを配列っぽく使うと配列と変わらない速度みたいです。
あと意外にもC++11から追加されたArrayはわずかながら配列より遅いみたいです。なぜでしょうか。
と思っていましたが、初期化を行ったうえで再実験行ってみたら配列が一番高速でした。次に、Array(C++11以降)が速いという結果となりました。

まとめ

今後はVectorを配列っぽく使います。
いや、修正した結果、配列が速かったのでやっぱり配列が一番ですね。

追記1(2016.07.09 0:27 UTC+9)

一部のコードを修正前のものを記載していました。修正しました。
なお、結果は修正後のものを記載しているため、変化ありません。

追記2(2016.07.09 0:52 UTC+9)

研究室の先輩(id:togatogah)から、「配列とArray(C++11以降)の初期化されていない可能性があるのに対し、Vectorは構築時に必ず初期化を行うので、配列とArrayを初期化してみてはどうか」という提案がありました。
そこで試してみたところ、大きく結果が変わりました。 id:togatogahさんありがとうございました。

プログラミング言語C++第4版

プログラミング言語C++第4版

【ネットワーク分析】 #1 グラフってなんぞや

最近真面目な投稿をしていないので、ネットワーク分析とかグラフ理論とかその周辺のアルゴリズムとかについてシリーズっぽくゆるゆると記述していこうと思います。
本シリーズでは、「ネットワークだぁ?グラフだぁ?全く知らないよ!」って方を対象に書いていくつもりです。

ネットワーク分析とは

ネットワーク分析とは、グラフ理論におけるグラフで表現したものに対する分析方法です。
対象となるデータは幅広く、SNSの繋がりとか感染症の伝搬だとか色々あります。

そもそもグラフとは

グラフ理論のグラフとかドヤ顔で言われてもわかんないですよね。いやそれが普通だと思います。
グラフとは、頂点(またはノード、V: Vertex)と辺(または枝、E: Edge)で表されるものと定義されています。
それらの集合を数学っぽく記述すると、
 V = \left\{v_1, v_2, \ldots , v_{N-1}, v_N \right\}
 E = \left\{e_1, e_2, \ldots , e_{M-1}, e_M \right\}
となります。これは、頂点N個と、枝M本の集合を表すという具合です。
頂点は、何か物(?)を示し、枝はその物々の繋がりを示します。
身近な例で言うと、高速道路の出入り口が頂点、高速道路そのものが枝だと考えたらわかりやすいかと思います。

f:id:cancolle:20160217213532p:plain
図1: 簡単な例・首都高のサイトより 引用元: http://search.shutoko.jp/

有向グラフと無向グラフと次数

グラフと言っても2種類あります。有向グラフと無向グラフです。
何が違うのかといいますと、有向グラフは向き(方向)が指定されており、無向グラフは向きが指定されていません。
また、頂点に接続している枝の数のことを次数といいます。
有向グラフにおいては、出次数(でじすう)と入次数(いりじすう)の2つが存在します。

無向グラフ

無向グラフとは、簡単に言うと、頂点間を結ぶ枝向きが指定されていないグラフです。
データセットとかのサイトに行くと、undirectedと記述されているものがそれです。
簡単な図で示しますと、以下の図2です。
f:id:cancolle:20160217211927p:plain
図2: 私が描いた無向グラフ

この図1では、
 \{v_1, v_2\}, \{v_1, v_3\}, \{v_1, v_4\}, \{v_2, v_3\}, \{v_2, v_4\},\{v_2, v_5\}, \{v_3, v_4\}, \{v_4, v_5\}
という枝があることが分かります。
次数ですが、 v_1から順に
3, 4, 3, 4, 2
となっており、最大次数は頂点 v_2 v_4における4となります。

てか、図汚いですね。はてなフォトライフめ・・・。

有向グラフ

有向グラフとは、簡単に言うと、頂点間を結ぶ枝向きが指定されているグラフです。つまり、どこからどこに向かって、枝があるのか…というのが表現できます。
データセットとかのサイトに行くと、directedと記述されているものがそれです。
簡単な図で示しますと、以下の図3です。
f:id:cancolle:20160217211937p:plain
図3: 私が頑張って描いた有向グラフ

このグラフですと、 v_1がモテモテですね。

出次数ですが、 v_1から順に
0, 4, 2, 2, 0
となります。
これは、点から出て行く枝の数を表します。わかりやすく言うと、何人に向けてラブレターを書いたかみたいな感じですね。

一方、入次数は v_1から順に
3, 0, 1, 2, 2
となります。
これは、店に入ってくる枝の数を表します。わかりやすく言うと、何人からラブレターをもらったかという感じですね。

隣接行列

グラフには、その隣接関係を示す隣接行列というものがあります。
簡単に言うと、どことどこがつながっとんねんって話です。
行、列ともに頂点集合に対応しています。
ちなみに、蛇足ながら書くと領域計算量は O(n^2)です(頂点の数をnとした場合)。

無向グラフにおける隣接行列

図2の例を元に隣接行列を書くと、

 
\begin{pmatrix}
0 & 1 & 1 & 1 & 0 \\
1 & 0 & 1 & 1 & 1 \\
1 & 1 & 0 & 1 & 0 \\
1 & 1 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 \\
\end{pmatrix}

となります。
無向グラフの場合、双方の向きを考慮しないため、行列は対称となります。

有向グラフにおける隣接行列

図3の例を元に隣接行列を書くと、

 
\begin{pmatrix}
0 & 0 & 0 & 0 & 0 \\
1 & 0 & 1 & 1 & 1 \\
1 & 0 & 0 & 1 & 0 \\
1 & 0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 \\
\end{pmatrix}

となります。
有向グラフの場合、向きを考慮し、それを隣接行列でも表現するため、行列は非対称となります。
行方向に攻め、列方向に受け、と考えると簡単だと思います。

今回のまとめ

簡単な事項について取り扱いました。
ループとか、重みとか、接続行列とか色々すっとばしていますが、今回はここまで…。