忘れん坊の備忘録

情報工学科に通う大学生のメモ。あまり詳しくは無いです。備忘録として殴り書き

擬似乱数について軽くまとめる

大学の授業にて乱数について教わりました

これが結構面白いし、今後の役に立ちそうなので忘れないように記述します


初歩的な話からすると、プログラムでの乱数生成は結構難しい
どうやって計算でランダムな値を出すかというのは簡単にはできないことです。

しかも、精度の高い偏りの無い乱数っていうものは大変なわけです
自分で偏りのないランダムな数字を計算で出してくださいって言われたら普通に無理って思います。



パソコンで生成される乱数はランダムに見えるけど、実は周期のある数列になります。
この乱数のことを「擬似乱数」と呼びます。

周期はあるんですが、かなり長いため実質ランダムだよねというのが擬似乱数の仕組みなわけです。




一番単純な擬似乱数生成アルゴリズムとしては "線形合同法” があります

このアルゴリズムは単純で高速に生成できるんですが、いろいろ問題があります
Xnが決まるとXn+1が決まってしまったり、パラメータを使うときに推奨値を使わないといけなかったり
とにかくあまりよくない方式です

C言語で使うrand()なんてのはこれの亜種が使われてます。(遅れフィボナッチ法?)
これだとXnが決まってもXn+1が決まらないようになってるそうです(よく知らない・・・)

C言語の乱数はseedが同じだと同じ乱数列が返ってきてしまいますよね
これはあまり良くないですが、実験を行う際などにはseed固定してバグを確認出来るので便利ではあります。


ここまでの乱数は割と良くない乱数なのであんまり使わない方が良いです

ってことで実用的な話をしていきましょう

今回話すのは2つ!
Mersenne Twister(MT)
・xorshift
です!!

Mersenne Twister(MT)

このアルゴリズムは今現在最も良い擬似乱数生成アルゴリズム!!(この改良版としてSFMTが出ていますが、ここでは同じものとして考えます)
・周期が長い!→(2^19937)-1
・結構、生成速度も早い!
・均等な分布で数値が出る!!(メモ:623次元超立方体で均等分布が保証されているとか言ってたけど良くわからなかった)

pythonはこのアルゴリズムが使われてるって聞いたことがある気がします(確証ないけど)
詳しい式が気になる人は調べてもらうと良いかなと思います。
(xorとか行列とかの式だったと思う)

以下のページが正式なホームページなので気になる方はどうぞ
Mersenne Twister: A random number generator (since 1997/10)

#xorshift

このアルゴリズムの良い点は
・めっちゃ単純
・めちゃくそ早い
・その割に精度良い!
みたいな感じです。
要はMTよりは精度良くないけど、早いし簡単にできて、精度もそれなりなんでコスパが良いってことです。
xorとシフトを使うだけで擬似乱数が生成できるという素晴らしさ

JavaScriptはこのアルゴリズム使ってるとか聞いた気がする

ついでにMT作った人たちが、このアルゴリズムに改良加えているサイトがあるのでこちらも参考に
XORSHIFT-ADD (XSadd)



軽くまとめたので、今後思い出す時の参考ぐらいかなぁ
実装自分でしてみるのも楽しいそう



ついでに良く使うC#の乱数アルゴリズム知らないなと思って調べました
"Knuthの差分乱数ジェネレータ"

知らないアルゴリズム出てきた・・・
これは、また今度調べます・・・。

Unityのファイル移動で困った話

久しぶりのブログになってしまいましたが、自分のメモとして更新します。

Unityでファイルを移動させたりフォルダを作ったりする時にmetaファイルも操作するのが面倒臭く、Unity側で作成しているAssetDatabaseというインタフェースを使うとmetaファイルごと操作してくれるのでそれを使っていました。

Unityではmetaファイルの操作は結構大事なので基本的にはAssetDatabaseを使ったほうが良いと思います。

AssetDatabase - Unity スクリプトリファレンス

行おうとしていた動作的には

ファイルを読み込む→名前に応じて自動でフォルダを作成→ファイルを移動

という処理なんですが、フォルダを作ってすぐに移動させようとするとエラーが😱

なぜ??と調べているとこんなサイトが見つかりました。

フォルダを作成する命令を実行した直後は、既存のフォルダを作成中なので、フォルダの容量とかがわからないから、unity内ではまだ、正確にフォルダの処理が行えないのだと思います。

Unity - UnityのEditorScriptに関して(28071)|teratail

なん・・・だと・・・????

どうやらフォルダが作られるまでラグがあって、フォルダが作られるまでは存在していない扱いで進められてしまうようです



ということで、作り終わるまで待つというスクリプトを書いたんですが死ぬほどわかりづらいのでやめました (これでやりたいという方はDictionary型で管理してfor分で回す感じになります)

AssetDatabaseは諦めてC#の標準File操作を使う羽目になりました。

metaファイルも自分で移動したりしないといけなかったので面倒くさいことにはなりましたがなんとか実装できました・・・。

追記>2018/8/15 C#のFile.Moveを使ってアセットを移動させmetaファイルを消去したら、OnPostprocessAllAssets()の第3引数に引っかからない結果になりました。 おそらくですが、metaファイルも移動させないとダメなんだろうなと思います




これと同じような感じでassetを読み込んですぐに設定を変えようとすると、エラーを吐かれました。

おそらくmetaファイルを一旦保存してからではないと移動できないという理由な気がします。


この辺りはmetaファイルのせいなきがするなぁ・・・・

metaファイル面倒くさい・・・・

環境:Unity5.3

<ad-live>アドリブワードで遊びたいからアプリ作るよ2

さて前回はアドリブワードを引けるアプリを製作した動機やアドリブワードについて話しました


前回はざっくりこんな感じ

  • ad-liveのギミックの一つであるアドリブワードめっちゃ面白いよ!
  • データベースに送信したアドリブワード保存して、アドリブワードを引けるようにしたいよね!
  • Unityで製作するよ!(いろんな環境で使えるもんね)


今回は細かくどう作ったのかなどを話していきます
製作期間は1日半ぐらいかな


まず、Unityで製作するにあたってどうやってネット上にワードを保存するのかが問題です

そこはさすがUnityという感じで便利機能たくさんあります

Unityではどうやらmbaas(mobile backend as a Service)と呼ばれる機能を提供してくれているとこがあるのでそれを使います
mBaaSとは | ニフティクラウド mobile backend


mbaasの中にデータストアと呼ばれるデータを保存してくれるものがあるのでこちらを使用しました


今回は主にmbaasのデータストアの使い方の備忘録となります(Unityの方の細かいことは書きません)
mbaas使ったのも1日半ぐらいなんでまだまだ初心者です。わからないことだらけですが忘れないように書きますよ


最初の入れ方などは簡単なので省略
イントロダクション (Unity) : クイックスタート | ニフティクラウド mobile backend
こういうの見ればすぐできます
ざっくり言うと
アカウント登録→パッケージインポート→テキトーにスクリプトとか貼り付ける


さてデータストアですが
f:id:kuhuhu1021:20170923004123p:plain
こんな画面です
ここにワードが追加されていきます


データストアのクラスの作成からです
これは画面の「クラス」と書いてある右の緑色のボタンを押して、新規作成すれば完成です


このデータストアを使ってどうやってアドリブワードを保存するかですが
データストアにkeyとそのkeyのvalueを送信して行います

実際にアドリブワードを保存してみると

f:id:kuhuhu1021:20170923004734p:plain

このような感じになります
自分自身が変更を加える場所としては"word"と"アドリブワードだよん"という場所になります
"word"がkeyになり"アドリブワードだよん"がvalueです
objectIdなどは勝手に登録されます
objectごとに割り振られますが、そんなの知らなくてもいいので必要ないことは理解しない主義で


Unityで使うためにまずどのデータストアのクラスを使うのかを取得する必要があります
そのコードが

NCMBObject obj = new NCMBObject ("ad_live_word");

これです
"ad_live_word"の部分をクラス名にすれば取得したいクラスを取得できます。



さて次に送信ですが送信する際にはどのkeyでどのvalueを送るかです
keyの名前などは自由に設定できます
今回はwordというkeyにしただけで、他のも可能ですし複数でもできるみたいです(あんまり知らない)

送信するコードですが

obj.Add ("word", "アドリブワードだよん");
obj.SaveAsync ((NCMBException e) => {      
    if (e != null) {
        //エラー処理
    } else {
        //成功時の処理
    }                   
});

だけです
objは先ほど取得したクラスのオブジェクトですね

obj.Add ("key名", String型の文字列);
で、できるのでUnity上から入力されたString型の文字列を取得してその変数を書けば終了です
めっちゃ簡単

エラー処理についてはこのまま書いておけば動くんで大丈夫です

送信は本当これぐらいしかしてません



次はアドリブワード取得の方です
アドリブワード取得の主な機能として

  • データストアからランダムでアドリブワードを取得
  • アドリブワードは一度引いたら捨てる
  • アドリブワードがそもそも一つも存在しないなら「ad-liveワードが存在しません」と出す

てな感じの実装をしてきます



ランダムで取得する方法を必死に考えました
よくわからんけどこんな記事を見つけました

大ヒットゲームアプリ「ひとりぼっち惑星」の裏側 ~前編~ | BACKEND AS A SERVICE mbaas BLOG

ここに今いくつワードがあるのか、取得件数の指定、取得開始位置の指定ができるのを発見

よし!ごり押しでいこう!
となった結果

今いくつワードがあるのか調べる
→取得件数を1つにする
→ワードの数までの中からランダムで一つ数字を選ぶ
→取得開始位置を先ほど選んだランダムな数字に決定
→取得したデータを表示、ワード消去

という見事なゴリ押しっぷり感

1つのみ取得する方法が調べてもわからずこんな感じになりました
誰か綺麗なコードかける人教えてください



まず安定のクラス取得から始まります
今回は

NCMBQuery<NCMBObject> query = new NCMBQuery<NCMBObject> ("ad_live_word");

こんな感じで書いたんですが上のと何が違うのか、いまいちよくわからない
こうやって公式に書いてあったんでこうしました

作れればいいよね!


次にいくつワードがあるか確認します
基本公式そのまんまです

query.CountAsync((int max , NCMBException e )=>{
			if(e != null){
				//件数取得失敗時の処理
			}else{
				//件数を出力
				if(max>0){
					Word_Max=max;
				}else{
					Ad_live.text="アドリブワードが存在しません";
				}

			}
		});

Word_Maxっていうのはいくつワードあるのか保存しとくためのint型の変数です
文字ワードがなかったら「アドリブワードが存在しません」とテキスト変更します




次にランダムで数字を決定しますこれはC#のランダムで値を決定する関数かUnityの関数でも使ってください
0以上Word_Max未満の範囲で決定します

今回はランダムで決定した値を"r"というint型変数に入れておきます
そこから取得件数と取得開始位置を決定します

query.Limit=1; //取得件数
query.Skip=r; //取得開始位置

これだけですが、取得件数の前に取得開始位置を置いたらうまく動作しませんでした
よくわからない仕様です
教えてください




次にワードを取得し、消去になります

foreach (NCMBObject ncbObject in objectList) {
				Ad_live.text=ncbObject["word"].ToString();
				ncbObject.DeleteAsync((NCMBException e2) => {
					if (e2 != null) {
						//エラー処理
						Debug.Log("エラー");
					} else {
						//成功時の処理
						Debug.Log("消去");
					}
				});
			}
		});

こんな感じです
メインは
Ad_live.text=ncbObject["word"].ToString();
これですね
Ad_liveというのはpublic Textなので変えるテキストになります
取得件数が1と決まっているのでforeachですが一つしかとってきません
この取得したのが開始位置が違うので、ランダムでncbObject["word"]からワードのデータを持ってくるわけです
最終的には消去して終わりという感じです

消去は
ncbObject.DeleteAsync((NCMBException e2)
から
});
までの文章になります
この場合はncbObjectがオブジェクトが入っているのでこれが消えます
keyやvalueを送信したやつ一つ一つがオブジェクトです

てな感じでだいたい実装できます




ただし、問題としてクリックを連続で行った時前の処理が終わっていないのに次に行かれると読み込み中なので取得できないので
今回はコールチンなどを使用しました
主にワードの件数を数え終えてからワードの表示とワードの消去を行うようにしました
(yield return StartCoroutine()とか使ったよ)




mbaasのことについてはだいたいメモできたのでこんなもんでしょう
意外と長くなりましたね


わからないとこや間違いの指摘などして頂くと勉強になるので喜びます


こんなのを参考にして製作しました
データストア (Unity) : 基本的な使い方 | ニフティクラウド mobile backend

<ad-live>アドリブワードで遊びたいからアプリ作るよ1

ブログってやっぱり続かないですね
たまに書くぐらいがいいです

そんなことはどうでもいいんですが、
2015年あたりから有名声優さんがやっているad-liveと言う90分間全てアドリブ舞台というものにはまっています

AD-LIVE(アドリブ) 2017 - AD-LIVE Project

声優さん自体あまり知らなかった私ですが、おかげでだいぶ詳しくなりました

今年もちょこちょこ見に行ってるわけなんですが面白いです!
(昼夜公演のどちらかを見に行ってます)


さて、この中に出てくるギミックで「アドリブワード」なるものがあります

[アドリブバッグ、アドリブワードとは]
アドリブバッグは、舞台上で出演者が常に持つバッグ。
アドリブワードは、そのバッグの中に入れられた紙に書かれている様々な言葉。

出演者は本番時、アドリブバッグから自由にアドリブワードを引く事が出来ます。物語の展開に即したワードを引けるか、あるいは、流れを著しく変えるワードを引くのか、それは投稿頂く皆様と、出演者次第。
引いたら、そこに書かれている言葉を必ず言わないといけないルールで、90分の舞台を紡いでいきます。

(ad-live公式ホームページより)


出演者が舞台に出るときにアドリブバックを持っていてその中にランダムでワードが書かれた紙が入っています
ワードはあらかじめ募集がかかっており、みんなが応募する参加型のギミックですね

この紙を引いたら絶対に言わなければいけないんですが、これが面白いんです

使い方としては
「私の好きな食べ物は『アドリブワード』です」
みたいな感じになるわけです

もちろん意味の通らないものが出てきたり、奇跡のように状況にあったワードが入っています

これがad-liveの醍醐味であったりしますね


舞台以外でも出演者発表会のときにワードを使ってアドリブトークなんかもやっています
これも非常に面白い



まぁそんなわけで、何が言いたいかというと

アドリブトークしたくね!?


これ実は姉と一緒にやったことがあります
紙にテキトーなワード書いてトークテーマ決めて、引いて遊びました
かなり面白かったですね

毎日やるのはしんどいですが、たまにやりたくなります

姉と二人でやった時の問題点として

  • 紙が大量に必要
  • ワードは自分たちで書いたものなので半分ぐらいは予測つく
  • 紙捨てるのもめんどくさい

みたいな感じになったわけです



ここまで色々な長い説明をしたわけですが何が言いたいかというと、
ネットにワードを保存して引くことができるアプリとか作れないかなーと思うわけですよ
(ad-live公式で出して欲しい)

ということで作りました


アドリブワード


見た目とかはテキトーです
(ボタンとテキストだけ)


今回はこの作った作品の備忘録になります

何で作ったかというと、なんでも万能なUnityちゃんです
Unity楽しいです

まぁUnityの勉強と思って製作した感じです


このアプリに関してはどこにもアップしません
そもそも、アドリブワードのアプリ出したら公式から怒られそうですし
Apple Storeにあげるのはめんどくさいし、学生からしたら登録の値段高いので嫌です
GooglePlayはアップできるっちゃできるんですが著作権的にアウトですね。はい。

てことで、個人利用のみですね・・・
本当はいろんな人のワード欲しい・・・
アドリブトークする相手欲しい・・・



ad-liveの語りばかりで、長くなってしまったので詳細は次に書きます。

Hadoopの設定

RaspberryPie2の設定が終わったので次はHadoopの設定を行っていきます
今回は
Raspberry Pi上でHadoopクラスタを構築する 〜インストールから擬似分散モードのテストまで〜 | MUDAなことをしよう。
こちらのサイトを参考にして行いましたが少しバージョンが違ったりします

まずは
Apache Hadoop Releases
こちらのサイトにてHadoopをダウンロードします
3.0.0.-alpha1というのが最新版でありましたがα版みたいです
動作が安定しない可能性があると困るので2016/11/15現在の2.〇.〇の中で最新である2.7.3をダウンロードしました
binary版をダウンロードして、解凍します
以下のコードを入力すれば大丈夫です

$ wget http://ftp.riken.jp/net/apache/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz
$ tar xzvf hadoop-2.7.3.tar.gz

Hadoop-2.7.3の設定の仕方については公式サイトにて載ってはいるのですが英語なので私には難しいです
Apache Hadoop 2.7.3 – Hadoop: Setting up a Single Node Cluster.
わかる人はこちらを参考にするといいと思います

HadoopにはJAVAが必要ですが、2.〇.〇ではjava8は対応していないのでjava7にしたほうがいいのかな?
まぁでもとりあえず8で動かしてみます

とりあえずわかる範囲で設定していきます
HadoopをダウンロードしたらJavaの場所を教えてあげる必要があるみたいです
ということで環境変数JAVA_HOMEを設定します
まずは

nano ~/.bashrc

と入力してエディタを起動します
そして

export JAVA_HOME="/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt"
export PATH=$PATH:$JAVA_HOME/bin

と、テキスト内に入力するのですが、Javaのバージョンによって最後の"jdk-8-oracle-arm32-vfp-hflt"のフォルダ名が変わってきてしまうのでそこは自分で調べてください
f:id:kuhuhu1021:20161115224523p:plain
nanoの閉じ方はcontrol+xで閉じられます
閉じる時にセーブしますか?と聞かれるのでyを押せばセーブできます

入力したら一旦、再起動して

echo $JAVA_HOME

と入力してみると
先ほどJAVA_HOMEに設定したフォルダの場所が帰ってくるはずです
私の場合は

/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt

と表示されました
これで確認できました

次に公式サイトにあるように

  $ mkdir input
  $ cp etc/hadoop/*.xml input
  $ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'
  $ cat output/*

と入力してみます
3行目でログが出ていたら、ちゃんと動作していると思われます

次に設定するのはetc/hadoop/core-site.xmlです。とりあえず擬似分散モードで設定します。
どうやらHadoopの各コンポーネントは、XMLファイルを使って設定されているようです。
Commonのプロパティはcore-site.xmlに、HDFSのプロパティはhdfs-site.xmlに、MapReduceのプロパティはmapred-site.xmlに入ってるみたいです。
また、2.0以降はMapReduceはYARN上で動かすのでyarn-site.xmlという設定ファイルも追加されているみたです。
それで、etc/hadoop/core-site.xmlを変更します。基本的にの間に設定は書くらしい

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

また設定中に”接続を拒否されました”という表示がたくさん出てきてわけわからんと思って悩んでましたがどうやらホスト名を設定すればいいようでした

sudo vim /etc/hosts

と入力して

127.0.1.1       raspberrypi

の下に

IPアドレス ホスト名

を追加することでできました。

以下の本を参考にしてたりします

Hadoop 第3版

Hadoop 第3版

raspberry Pie2 macを使って設定とか

まずはOSのを公式サイト
Raspberry Pi Downloads - Software for the Raspberry Pi
からダウンロードします

NOOBSLiteの方(こちらはネットからインストールする方)を選択しました
→オフラインならLiteがつかない方

OSをSDカードにインストールする時は
ディスクユーティリティを開いてFAT32でパーテーションはマスターブートレコードにします
これをしないと上手く起動しません
色々な設定はこのサイトを参考に進めました
qiita.com

ラズパイをいちいち起動するのが面倒くさいということでmac上でssh接続をして動かすことにしました
ssh接続にするためには色々設定してから

ssh -l pi IPアドレス

とコマンドで入力
1回設定しとけば次回からこれをターミナル上で入力すれば大丈夫
下記のサイトを参考にしながらssh接続の設定を行いました
www.stdio.jp


ssh接続をやっていて、コマンドだけの操作が嫌だったので調べたところvnc接続とやらがあるみたいで
結局それを使いました
darmus.net
こちらを参照して設定しました。
起動する時はラズパイ上で

tightvncserver

と入力
接続する時は、macのデスクトップ上でcommand+Kを押して
サーバーアドレスというところに

vnc://IPアドレス:5901

を入力
これでパスワードを入れれば立ち上がるはず

とりあえずラズパイの設定はこんなもんだと思います

Hadoopを始める前に情報集め(知識が乏しい人向け)

学校の授業にて教授に言われたのでHadoopとRaspberryPi2を使って並列処理を行うことになりました
正確にいうと誘導尋問的な感じでなってしまったんですが、まぁやってみるのもいいかなって思ったので


もともとソフトウェア系しか知らないのにいきなりハードウェアに近いものになってしまったのでちんぷんかんぷん
できるか不安です

とりあえず、ラズパイを2つ繋げるのを目標にします

とにかく情報が少ないので言われた単語をメモして調べました

Hadoopとは

並列分散処理を支えるミドルウェア

と書かれていました
要は並列分散処理を行うときに管理してくれるもの的な感じでしょうか・・・
www.slideshare.net
こちらのスライドはわかりやすかったので参考にしました。
どうやらHadoopJavaが必要みたいなのでJavaの勉強をしなければ・・・


次に、MapReduceですが、行う処理を分割してそれぞれのコンピュータで行い、その処理を集めて最後に出力するという認識で良いのかな?
手法の一つって感じかな

MongoDBですがNoSQLと呼ばれるデータベースの1つです
これを使ってデータベースの処理をしてみたらと教授に言われました
www.publickey1.jp
おそらく、Hadoopとの相性が良く並列処理を行うときにデータベースを使えってことだと思います
そもそもデータベースも学んだことがないポンコツなので、さらに謎が深まりましたがこれは一旦置いておきます
まずはRaspberryPi2を設定してHadoopを入れることから始めなければ

Hadoopはこちらのサイトからダウンロードできます
Welcome to Apache™ Hadoop®!