3秒でわかる「積率(モーメント)」【確率統計学】
積率とは
確率分布の特徴を調べるために扱う値です!
標本と確率の積、つまり期待値を扱って定義されます。
詳しく
上の式を「xの原点周りのk次の積率」と呼びます。
また、
上の式を「xの期待値周りのk次の積率」と呼びます。
積率を使うことで期待値、分散、歪度、尖度を表現できます。
期待値
分散
歪度
尖度
参考にしました
3秒でわかる「頂点シェーダー」【Unity】
頂点シェーダーとは
(主に)頂点の座標等を操作するシェーダーです!
Vertex Shader(バーテックスシェーダー)とも言います。
頂点シェーダー部分はHLSL言語で書かれています。
デフォルトのシェーダーを作る
「Project」上で右クリックして、 Create -> Shader -> UnlitShader と選択するとシンプルなシェーダーができます。
デフォルトのUnlitShaderからFog周りを省いたものが以下のコードです。
Shader "Unlit/NewUnlitShader"{ Properties{ _MainTex("Texture", 2D) = "white" {} } SubShader{ Tags { "RenderType" = "Opaque" } LOD 100 Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag //入力用の構造体 struct appdata { float4 vertex : POSITION; //頂点の座標 float2 uv : TEXCOORD0; //頂点に設定されたuv座標 }; //出力の構造体 struct v2f { float4 vertex : SV_POSITION; //頂点の座標 float2 uv : TEXCOORD0; //頂点に設定されたuv座標 }; //頂点シェーダー v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); //頂点の座標をクリップ空間での座標に変換 o.uv = v.uv; //uv座標はそのまま return o; } sampler2D _MainTex; //フラグメントシェーダー fixed4 frag(v2f i) : SV_Target{ fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }
このコードから、頂点シェーダーに関わる部分を抜粋します。
頂点シェーダーに関わる部分
#pragma vertex vert
ここで頂点シェーダーメソッドを設定しています。
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
頂点シェーダーに渡す引数を構造体で定義します。
変数のコロン(:)の後に書かれている大文字のキーワードは、「セマンティクス」といいます。
レンダリングの過程で渡される、もしくは渡すデータがあらかじめ決まっていて、どの引数にどのデータが対応しているかをここで書きます。
この構造体では入力用のセマンティクスを対応させます。
「POSITION」は座標データで、「TEXCOORD0」が頂点に対応しているuv座標です。
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
頂点シェーダーが渡す値を構造体で定義します。
ここでは出力用のセマンティクスを対応させます。
「SV_POSITION」は座標データで、「TEXCOORD0」が頂点に対応しているuv座標です。
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
頂点シェーダーのメソッドです。
ここで実際の処理をします。
UnityObjectToClipPos()を使って頂点座標をクリップ空間座標へと変換します。
クリップ座標系については以下のページを参照してください。
blog.natade.net
また、ここではuv座標は特に加工せずそのまま渡しています。
そしてフラグメントシェーダーへ
頂点シェーダーでの処理が終わったら、カリングやラスタライズを経て「フラグメントシェーダー」の処理に進みます。
(参考)入出力セマンティクスの種類
3秒でわかる「分散」【確率統計学】
分散とは
データのちらばり具合です!
分散という言葉からもなんとなくそんな感じがしますね!
身長の分散
A~Dさんがいるとします。
この4人の身長の分散を計算しましょう。
(1) 4人の身長の平均()
(2) (1)の二乗()
(3) 4人の身長の二乗の平均()
よって分散は、
です!
では、4人とも同じ身長だったらどうなるでしょうか?
全員140cmだとして、
(1) 4人の身長の平均()
(2) (1)の二乗()
(3) 4人の身長の二乗の平均()
分散は、
です!
分散は値が大きければ大きいほどデータが散らばっているのがわかりますね。
今回はこれで終わりです!
3秒でわかる!「中央値」【確率統計学】
中央値とは
集まりのちょうど真ん中のことです!
詳しく
確率をとして、
を満たすを中央値と言います。
集まりを小さい順に並べて、小さい順(大きい順)に集まりの数の半分まで数え上げると、中央値がわかります。
集まりの数が偶数の時は集まりの数の半分が二つあるので、その二つの平均が中央値です。
また、確率変数をx、確率関数をf(x)として、
を最小にするも中央値になります。
年収の中央値
年収は何億何十億と、ものすごい稼いでいる人もいます。
なので、平均値(期待値)にすると、「あれ?平均でみんなこんなに稼いでいるのか・・・」となります。
中央値は「集まりのちょうど真ん中」をみるので、集まりで一番稼いでいる人などのデータが邪魔しません。
中央値は外れ値に強いのです。
実際に、平成29年度の日本人全体の平均年収は432万ですが、中央値を国税庁のデータから推測すると、300~400万の間になります。
3秒でわかる!「カスタムコルーチン」【Unity】
カスタムコルーチンとは
自分で実装するコルーチンです!
作り方
分指定で待ってくれるコルーチンを作ります。
(1)クラスを定義
public class WaitForMinutes{ }
(2)CustomYieldInstructionを継承
using UnityEngine; public class WaitForMinutes : CustomYieldInstruction { }
(3)keepWaitingをオーバーライド
抽象メソッドを実装しよう。
public class WaitForMinutes : CustomYieldInstruction { public override bool keepWaiting { get { return true; } } }
(4)機能を作る
コンストラクタを定義しよう。
using UnityEngine; public class WaitForMinutes : CustomYieldInstruction { private float waitTime; //実際の待ち時間 public WaitForMinutes (float time) { waitTime = Time.realtimeSinceStartup + time * 60; } public override bool keepWaiting { get { return (Time.realtimeSinceStartup < waitTime); } } }
(5)あとは使うだけ!
using System.Collections; using UnityEngine; public class Test : MonoBehaviour { private void Start () { StartCoroutine(TestCorountine()); } private IEnumerator TestCorountine () { yield return new WaitForMinutes(5); Debug.Log("Waited 5 minutes."); } }
シーンファイルの正体【Unity】
Unityを使っているとき、ほぼ確実に使う「シーンファイル」。
拡張子は.unityで、シーンを保存すると作成されます。
けどこれ何を保存してるんだろう・・・
シーンの情報が入っているんだろうけど・・・
・・・
気になったので調べました!
今回使用したUnityのバージョンはUnity2018 3.7f1です。
SampleScene.unityはこんなかんじ
%YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!29 &1 OcclusionCullingSettings: m_ObjectHideFlags: 0 serializedVersion: 2 m_OcclusionBakeSettings: smallestOccluder: 5 smallestHole: 0.25 backfaceThreshold: 100 m_SceneGUID: 00000000000000000000000000000000 m_OcclusionCullingData: {fileID: 0} --- !u!104 &2 RenderSettings: ・・・ [中略] ・・・ --- !u!4 &534669905 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 534669902} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
結構長い(266行)
ぱっと見たところ、RenderSettingsやGameObject、Transformといった単語が見られます。
それに階層分けされている雰囲気です。
ゲームオブジェクトを新たに作成するとどうなるのか
以下の部分が追加されました。
--- !u!1 &1828928079 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - component: {fileID: 1828928080} m_Layer: 0 m_Name: GameObject m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!4 &1828928080 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1828928079} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
これを見ると、
--- !u!1 &1828928079
の部分が始まりで、その下に、
GameObject: Transform:
といったようなコンポーネントの情報が続いています。
Transformを変更してみた
--- !u!1 &1828928079 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - component: {fileID: 1828928080} m_Layer: 0 m_Name: GameObject m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 --- !u!4 &1828928080 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1828928079} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 1, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
Transform:以下のm_LocalPosition:の部分が{x: 1, y: 0, z: 0}に変わっています!
では、シーンファイルのデータを直接変えたらどうなるでしょうか?
Transform:以下のm_LocalScale:を{x: 2, y: 1, z: 1}に変えてみます!
外部変更が検知され、
Unity上でも変更が確認できました!
--- !u!1 &1828928079の部分はどういう意味か
!u! の後がクラスIDで、
& の後がファイル内で一意に割り振られるオブジェクトIDです。
クラスIDの一覧はこれです。
docs.unity3d.com
ここにも書いてあるとおり、自分でスクリプトを作成してアタッチするとクラスIDは114(MonoBehaviour)になるそうです。
おわりに
ある程度は直接unityファイルから編集できそう(バグ起きそうだけど)なので、うまいことシーンファイル内部を参照できれば不思議なことができそうです。
共同開発でしばしばコンフリクト起こす場所でもあるので、内部が少し把握できると対策案が組めそうですね。
参考にしました
C#からPythonを実行する方法【Unity】
UnityとPythonをつなげてやりたいことがあります。
Pythonで機械学習して、Unityで作ったゲームの中で使う、そんな感じのことがしたいのです。
なのでまずはPythonをどうやって実行するか、というところが課題でした。
調べてみると案外あっさり見つかったので、手順とポイントをまとめていきます!
参考にしたサイトはページ下部にリンクを張るので、そちらを見てください!
Unity(C#)側
using System.Diagnostics; using System.IO; using UnityEngine; public class CsPy : MonoBehaviour { //pythonがある場所 private string pyExePath = @"(Pythonの実行ファイルが置いてある場所)\python.exe"; //実行したいスクリプトがある場所 private string pyCodePath = @"(実行したいスクリプトの場所)\tst.py"; private void Start () { //外部プロセスの設定 ProcessStartInfo processStartInfo = new ProcessStartInfo() { FileName = pyExePath, //実行するファイル(python) UseShellExecute = false,//シェルを使うかどうか CreateNoWindow = true, //ウィンドウを開くかどうか RedirectStandardOutput = true, //テキスト出力をStandardOutputストリームに書き込むかどうか Arguments = pyCodePath + " " + "Hello,python.", //実行するスクリプト 引数(複数可) }; //外部プロセスの開始 Process process = Process.Start(processStartInfo); //ストリームから出力を得る StreamReader streamReader = process.StandardOutput; string str = streamReader.ReadLine(); //外部プロセスの終了 process.WaitForExit(); process.Close(); //実行 print(str); } }
python.exeの場所と、実際に実行したいpythonスクリプトの場所のフルパスをコード内に書きます。
Processクラスを使用して外部のファイルを実行します。
今回は、実行したpythonスクリプトから得たストリームを文字列にしてunity側で使います。
Python側
import sys #引数を得るために使用 playerSelect=str(sys.argv[1]) print( "REPLY[" + playerSelect + "]:" + "Hello,CS." )
sysライブラリを使用して、c#側から送った引数を使用します。
printした文字列が、c#側のストリームに送られます。
実行すると
うまくやり取りできました!
参考にしたサイト
3秒でわかる「期待値」【確率統計学】
期待値とは
「起こることの数値」×「起こる確率」の合計です!
確率分布の真ん中がわかります。(外れ値がある場合感覚的に変な数値になる)
式
を確率変数、を確率関数、期待値を]とする。
期待値はのによる重み付き平均として定義する。
(1)確率変数が離散値
(2)確率変数が連続値
ロト6の期待値
ロト6の当選金額と確率はこんな感じです。
1等 1/6096454 2億円 2等 6/6096454 1000万円 3等 216/6096454 30万円 4等 9990/6096454 6800円 5等 155400/6096454 1000円 はずれ 0円
期待値を計算すると、
期待値は90でした!
ロト6は一口200円なので、仮に全部買ったら45%回収できる計算ですね。
運よくないと厳しそうですね・・・。
FGO(Fate/Grand Order)の期待値
FGOはスマートフォンゲームです。
コンテンツなので、それにどのくらい価値を感じるかで損得が変わってきます。
仮に価値を割り振ってみましょう。
最高レアリティキャラ 1/100 30000円 それ以外 99/100 0円
期待値は300となります。
このコンテンツに30000円の価値を感じているとするなら、300円で当てるとお得ということです。
FGOでのガチャ一回の値段は一番安い条件で176円なので・・・
1回で引かないと損!(暴論)
・・・
ガチャ1回の価値は人それぞれです。(たぶん多くの人にとっては)もっと高くなります。