Java FX in RPi 〜ラズパイで動くJavaFX〜

Javaで作成する、画面アプリをラズパイで動かそうと言うものです。
今回は、作成したアプリをラズパイ上で動かし、「Youtubeプレイヤーとして動かそう!」と言うものです。

JavaFX in RPi

開発環境構築

前提として、自分が使用している開発環境について記載します、

  1. SceneBuilderを使用しています。(JavaFXの初期コード生成などしてくれます)
  2. JDK1.8を使用(RPiもJDK1.8を使用します)

SceneBuilderのインストール

こちらの記事にインストール手順と実際に動かした時の内容を記載しました。(動かしてみた時の記事)
このセットアップをしておくとJavaFXのプロジェクトを作成した時に、下のようなコードを生成してくれます。

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

ちなみに、プロジェクトをMaven化しているのでPOMファイルがあります。生成されるのはapplication.cssとMain.javaです。

開発開始

現状(上こコード)では下のような表示ができます。

まぁ何も実装していないので何もないです(笑)
ここに必要なもの(コンポーネント(ボタンなど))を追加していきます。

設計

設計の大まかなところはGithubにアップしています。
なので、とりあえずはURLをロードして、表示する画面を作成します。
大まかな仕様は以下の通りです。
<仕様>

  1. JavaFXを起動
  2. プロパティファイルをロード(読み込む)
  3. プロパティファイルにあるURLを読み込み表示する

とりあえずはここまで実装しようと思っています。

JavaFXの起動

とりあえず生成されたコードで動いているので、この部分は飛ばします。

1.プロパティファイルの読み込み

RPi(ラズパイ)で動かす時にはMavenのプラグインで出力するJARファイルを起動して動かすので、別途プロパティファイルをJARファイルの隣(同じ階層)に配置する必要があります。
しかし、開発段階では気にしなくて良いので、resources/いかにプロパティファイルを配置します。

そんなわけで実装開始〜

プロジェクトの設定

単純に使用したいライブラリ、JARファイルの出力を設定します。
まずは使用するJUNIT(使い方など)dependencyに追加、使用できるようにします。

ちなみに、EclipseのMavenプロジェクトの場合はPOMファイルに下のような設定をかき、ビルド(Install)すると必要なライブラリが追加されます。

実行するときは下のようにPOMファイルを右クリックして Maven Installを実行します。

ちなみに、自分が作成したPOMファイル(コピペで作成)は以下のようなものです。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>RPiMediaPlayer</groupId>
  <artifactId>RPiMediaPlayer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>RPi メディアプレーヤー</name>

<!-- 必要な情報をプロパティとしてもつ -->
  <properties>
      <java.version>1.8</java.version>
      <maven.compiler.target>${java.version}</maven.compiler.target>
      <maven.compiler.source>${java.version}</maven.compiler.source>
  </properties>  
<!-- 使用したいライブラリ(依存性)の設定 -->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
<!-- ビルドの設定 -->
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
            <mainClass>zenryokuservice.socket.server.SocketServerBasic</mainClass>
            <classpathPrefix>dependency-jars/</classpathPrefix>
          </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id> <!-- this is used for inheritance merges -->
          <phase>package</phase> <!-- bind to the packaging phase -->
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>2.5.1</version>
      <executions>
        <execution>
          <id>copy-dependencies</id>
          <phase>package</phase>
          <goals>
          <goal>copy-dependencies</goal>
          </goals>
          <configuration>
           <outputDirectory>
             ${project.build.directory}/dependency-jars/
           </outputDirectory>
          </configuration>
         </execution>
       </executions>
     </plugin>
    </plugins>
  </build>
</project>

実装まで行きませんでしたが、ここら辺で失礼いたします。

でわでわ。。。



Java FX RPi Media Player 〜ラズパイ・メディアプレーヤー〜

今回は、ラズパイ上で動くメディアプレーヤーを作成しようと思います。

経緯

本当はYoutubeを再生するアプリを作成しようとしたのですが、これを設計している最中に「作成していく途中で結局メディアプレーヤーを作ることになるな・・・」と思い、このようになりました。

開発準備

いつも通りに、Eclipseを使用します。

そして、セットアップ関連はこちらの記事を参考にしてください。

Windows版はこちらの記事でEclipseのインストールを行いました。

ラズパイで動かす

今までにラズパイ上で動かすため、Eclipse Kuraのセットアップに挑戦していましたが、ちょっとこちらをストップ。
シンプルにJavaSE(JDKに入っているAPI)で進めてみようと思いました。

JavaSEはラズパイだろうが、PCだろうが、Arduinoだろうが動かすことができます。
ただし、Bluetoothなどのデバイスにアクセスしたい場合には、以下のような手間があります。

  1. ちょっとしたライブラリを使用
  2. 自分でデバイス用のプログラムを書く

なので、今回はそれらを使用しない方法でやろうと思います。
つまり。。。

JavaSEでの開発

Java 8 以降、JavaSEにはJavaFX(画面作成API)が梱包されているので、そのまま使用することができます。
具体的には下のようなコンポーネント(画面とか、ボタンとか)をJavaで作成、動かすことができます。
下のものは JavaFXでのサンプルアプリです。

そして、自分が作成したものです。

これらは、Javaのみで(PCに付けたUSBとかディスプレイなど)にアクセスしないで起動できるのでJavaSEのみで作成、起動することが可能です。

と言うわけでJavaFXでの開発方法を以下にまとめます。

開発方法

実際に開発するのには、手間が少ない方が良いです。(みんなそう思うし、時間ができれば色々なことができます)
なのでなるべくなら「手間を少なく」「良いアプリを作る」ここら辺に注力して準備を進めたいと思います。

  1. NotePCでのEclipseでの開発(プログラム作成)
  2. NotePC上でテスト(ローカル・テスト)
  3. RPi上でテスト(実機テスト)

こんな感じで開発を進めたいのですが、これを実現するためにMavenを使用します。
英語のサイトなので日本語訳してみます(最近のものは意味がわかるようになってきています)

まとめると下のようになります。

  1. Eclipseにプロジェクトを作成する
  2. Githubにリポジトリを作成する
  3. NotePC上でテストしたコードをコミット(PUSH)
  4. ラズパイでGithubからPULLしてソースを取得
  5. Mavenビルドで起動ファイル(*.JAR)を生成
  6. ラズパイのSHELLでOS起動時に動かす

まずはNotePCで動かす

そんなわけで、NotePC上で開発を始めます。ちなみに、上の手順「4」の確認は行いました。ハローワールドプログラムを起動することに成功しています。JavaFXも起動確認済みです。ただし、Xサーバー(GUIサーバー)を起動する必要があるのでラズパイをCUIモードで動かすとJavaFXが動きません。。。

ちょっと長くなってきたので、今回はここまでにします。

でわでわ。。。

関連ページ

Eclipseのインストール〜java学習フロー



数学への挑戦 第二弾〜まとめ1:数理モデルxプログラミング〜

前回は確率変数の足し算を行いました。しかし、イマイチな感じです。。。
なので、これらをまとめるために「樹形図」を使用して今までの学習したものをまとめようと思います。

今までのまとめ

  1. 傘を持っていくべきか、持っていかないべきか?
  2. 数理モデルをJavaで表現する
  3. 喫煙率を求めるモデル
  4. コインの表裏(確率変数)
  5. コインの表裏(期待値と分散)
  6. 卒業までに彼氏ができる確率
  7. 確率変数の足し算

使用する書籍は下のものです。

1.傘を持っていくべきか、持っていかないべきか?

ここでは、傘を持っていくことの嫌度(損失)を-2とし、雨に濡れることの嫌度(損失)を-10として計算式(数理モデル)を作成しました。
ポイントは「全てのケースに対する結果を数値化する」と言うところでした。
具体的には以下のようになります。

<前提>
行動の選択肢は「傘を持ってくる」 or 「持ってこない」の2つ
<嫌度>
雨に濡れることの嫌度 = -10(濡れないとき = 0)
傘を持ってくることの嫌度 = -2
<確率>
雨の確率: 60% = 0.6
晴れの確率: 40% = 0.4

上記のようになります。

平均的な損失を求める

上でまとめたものを表にすると下のようになります。
<天気(確率 : 嫌度)>

傘を持ってくる 持ってこない
Ⅰ 晴れ(0.4 : -2) Ⅲ 晴れ(0.4 : 0)
Ⅱ 雨(0.6 : -2) Ⅳ 晴れ(0.6 : -10)

これらの結果(Ⅰ -> Ⅳ)から平均を求めると

<傘を持ってきた場合の損失>
Ⅰ + Ⅱ + Ⅲ + Ⅳ = (0.4 - 2) + (0.6 - 2) = -0.8 - 1.2 = -2のようになります。
<傘を持ってこない場合>
Ⅰ + Ⅱ + Ⅲ + Ⅳ = (0.4 0) + (0.6 -10) = 0 - 6 = -6

2.数理モデルをJavaで表現する

そして、変数にできるものを変数化(一般化)してやるとしたのようになる。

降水確率60% = 0.6 = p : 晴れの確率40% = 1 - p
雨に濡れる嫌度 = -10 = -c : 傘を持ってくる嫌度 = -c/5

雨の場合
(0.4 x -2) + (0.6 x -2) = -2 => ((1-p) x -2) + (p x -2) = (-2 + 2p) + (-2p) => 平均は「-2」
晴れの場合
(0.4 x 0) + (0.6 x -10) = -6 => ((1-p) x 0) + (p x -10) = 0 + -10p = 平均は「-10p」

ここで「雨に濡れる嫌度が1/5」になっているのでこれも変数化します。変数名は「a」にします、そして割合なので0 < a < 1」になります。まとめると以下のようになります。

雨の確率 = p : 晴れの確率 = 1 - p
雨に濡れる嫌度 = -c : 傘を持ってくる嫌度 = -ac

これを式にすると。。。

傘を持って来た時
((1-p) x -ac) + (p x -ac) = (-ac + pac) + (-pac) = -ac
傘を持ってこなかった時
((1-p) x 0) + (p x -c) = (0 - pc) = -pc

結果として、

a > p

なので、「雨の確率がa(傘を持ってくる嫌度の割合)より大きい時」ということになります。

3. 喫煙率を求めるモデル

回答のランダム化で、出た結果のグループ分けを行う
1.Aグループ = コインで表が出た人
2.Bグループ = コインで裏が出た人
3.Cグループ = Aの中でタバコを吸った人
4.Dグループ = Bグループでタバコを吸った人

実際に行ってはいないけれど「仮に」喫煙者が400人いたとするのであれば、喫煙率は「400 / 1000 = 40%」になるので「コイントスでA, Bグループ(500人ずつ)にいる喫煙者社の割合(確率)も40%で200人ずついることになる。

求めるべき値の喫煙者数=400は下のようにして求めることができる。

|B U C| = |B| + |C|
|B U C| - |B|=  |C| 両辺から|B|を引く

下の値を使用して計算すると。。。
|B U C|=600, |A|=500, |B|=500
次のような計算式で求めることができる
|B U C| - |B| = |C| = 100
|C| / |A| = 100 / 500 = 0.2 = 40%
となる。。。つまり喫煙者の割合は「40%」になり「仮定」で示した「400」と言う数値も正しいものであると言える。

と言うような感じで、集合を使った時の考え方を学びました。

4. コインの表裏(確率変数)

確率変数

前回の話では、コインの表裏を使ったので下のような確率が存在します。

出来事 確率
裏が出る 0 0.5(1/2)
表が出る 1 0.5(1/2)

そして、出来事の集合をΩ={裏, 表}のように表現します。
さらに、(わかりやすいように)コインがちょっと曲がっていて上の確率が変わり下のようになったとします。(仮定)

出来事 確率
裏が出る 0 0.4
表が出る 1 0.6

ここでの「0」「1」が確率変数というものになります。

サイコロの場合
目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

5. コインの表裏(期待値と分散)

目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

期待値

期待値=<確率変数の実現値> x <実現値の確率>の合計

つまり、サイコロの期待値は・・・

(1 x 1/6) + (2 x 1/6) + (3 x 1/6) + (4 x 1/6) + (5 x 1/6) + (6 x 1/6) = 3.5となる。

6. 卒業までに彼氏ができる確率

「出会った男性が青葉のことを好きになる or ならない」で考えます。

好きになる 好きにならない
1 0

そして、確率変数の時と同じように表にすると下のようになります。

出来事 確率
好きにならない 0 1 - p
好きになる 1 p

P(X1 = 1) = p
P(X2 = 0) = 1-p

これが、ベルヌーイ分布というもだと書いてありました。

確率変数Xが、「確率pでX=1」となり、「確率1-pでX=0」となる時、確率変数Xはベルヌーイ分布に従う、という

男性1(X1) 男性2(X2) 男性3(X3) 合計
No No No 0
Yes No No 1
No Yes No 1
No No Yes 1
Yes Yes No 2
Yes No Yes 2
No Yes Yes 3
Yes Yes Yes 3

上の表が起こりうるパターンを一覧化したものです。
これらの期待値を算出するためにはどう考えたら良いかを学習しました。

7. 確率変数の足し算

上の表にあるもので実際に同時には起きない事象があります。

X1, X2の独立下確率変数を1つの塊としてみる

と言うことが「確率変数の足し算」と言う意味です。
これはどう言うことかと言うと

「男性1が好きになり、男性2が好きにならない」という事象と「男性2が好きになり、男性1が好きにならない」という事象は「同時に起きない」

と言うことなので、

パターン数が1のもの(合計が0 or 3)

① P(X1 + X2 + X3 = 0) = P(X1=0, X2=0, X3=0) = P(X1=0)P(X2=0)P(X3=0) = 1/2 x 1/2 x 1/2 = 1/8

②P(X1 + X2 + X3 = 3) = P(X1=1, X2=1, X3=1) = P(X1=1)P(X2=1)P(X3=1) = 1/2 x 1/2 x 1/2 = 1/8

パターン数が2のものは合計が(2になるもの)

③ P(X1 + X2 + X3 = 2) = P(X1=1, X2=1, X3=0) 
+ P(X1=0, X2=1, X3=1)
+ P(X1=1, X2=0, X3=1)

= P(X1=1)P(X2=1)P(X3=0) 
+ P(X1=0)P(X2=1)P(X3=1)
+ P(X1=1)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

パターン数が3のもの(合計が1)

④P(X1 + X2 + X3 = 1) = P(X1=1, X2=0, X3=0) 
+ P(X1=0, X2=1, X3=0)
+ P(X1=0, X2=0, X3=1)

= P(X1=1)P(X2=0)P(X3=0)
+ P(X1=0)P(X2=1)P(X3=0)
+ P(X1=0)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

これらを表にすると
<X1 + X2 + X3>

実現値 0 1 2 3
確率 1/8 3/8 3/8 1/8

とちょっと長くなりましたが、こんな感じで学習してきました。

これから、ちょいと学習レベルを上げていく感じです。
つまり、実際に数理モデルを扱うための学習になって行きます。

でわでわ。。。



Java IoT 予備知識〜ラズパイにJava(Web)サーバーを立てる〜

ラズパイにIoT開発環境を構築するというミッションがあるのですが、急遽ラズパイにJava製のWebサーバーを起動しようということになりました。

JavaのWebサーバー

とりあえずはここのページを参考に作成しようと思います。

結論から言うと。。。

HttpServletクラスを拡張(extends)してリクエストを受け付ける常駐アプリを作成しようと言うことです。

とても、シンプルなJavaウェブサーバーです。Java出なくてもクライアントとサーバーの関連を学習したい人は一読作成して見ると、一発で理解できます。(理解できないと作成できません。)

このような、低レベルな実装は経験する機会があまりないので、Java学習者やウェブデザイナーなどウェブ・サーバーをよく使う人には一度やって見ると理解が早いです。

大まかな仕組み

下のような図になります。

ふざけているのではありませんので。。。

クライアント(スマホやPC)からURLを指定してサーバーにアクセスします。

クライアントはPCやスマホなので自分が持っている機械(デバイス)です。

そして、サーバーはどこかの会社とか、国の機関とかにおいてあるウェブサーバー(アプリ)を起動している機械(デバイス)にアクセスしてそのアプリが返却するHTMLを見ている状況です。一緒にJSなどもダウンロードされて画面(ブラウザ)に表示されます。

大まかに上のような処理を行う「ウェブサーバー」をJavaを使用して作成しようと言う考えです。

サーバーはアプリのこと

サーバーはアプリケーションです。常駐指定動くアプリのlことを「サーバー」と呼びます。
具体的には、PCを動かすために起動する(画面を表示する)Xサーバーなんてものもありますし、電源を入れたらスマホの画面が開くのも常駐アプリなので「サーバー」の仲間に入ります。
全部がサーバーだと呼ぶのに不便なのでスマホアプリと言ったり、サーバーと言ったりして区別します。

Java版Webサーバー

通常は、TomcatとかApacheとかをダウンロードしてきてウェブサーバーとして稼働することが多いのですが、今回はこれをJavaで作成しようと思います、まずは調査から行きますが、TomcatはJavaでできているようです。

JavaでのWebサーバー

このサイトを参考にしました。

結論から言うと、ServerSocketで受付(ポートを指定してリスン状態で待機)してHTTPメッセージを返却する。と言うものがWebサーバーの正体のようです。

シンプルなSocketサーバーは以前作成しました。

これを一度作ったことがあるならば(ServerSocketアプリのことです)わりかし簡単に作成することができると思います。

Httpメッセージ

よく、「Httpヘッダー」とか「Httpボディ」とか言ったりしますがHttpメッセージの「ヘッダ」「ボディ」と言うのが正確な言い方です。

参考の処理内容

  1. ServerSocketをXXXポートで待機
  2. リクエストを受け付けたら、受け取ったメッセージ(Httpメッセージ)から相手のIPを取得
  3. IPを使用してHttpレスポンスを作成
  4. OuputStreamでリクエスト元に返却する(レスポンスを返却する)

と言うような流れで処理を作成しているようです。

レシピ

詳細に関しては、Java APIを参照してください。

  1. ServerSocket
  2. BufferedReader(Reader)
  3. DataOutputSream(OutputSream)

こんなくらいです。

webサーバー

  1. リクエストを受けて(SocketServer#accept())
  2. リクエストの値からファイルを読み込む
  3. HTTPメッセージボディにHTMLを書く
  4. データ(DataOutputSream)を返却

シンプルにこんな手順で処理を行えば良いと思います。

低レベルなAPIは、全て作成する必要がありますが、逆に言えば全てが想い通りに作れると言うところが魅力的(笑)

こんな感じで考えております。このアプリにどんな機能を追加するかは作成者の思うままですね。。。

何やろうかな?

でわでわ。。。



数学への挑戦 第二弾〜確率変数の足し算:数理モデルxプログラミング〜

今回は確率変数の足し算を学習します。
そして、学習に使用する本は下のような本です。

前回使用した表は下のようなものです。
この本に登場する、女子大生「青葉」の彼氏ができるか?を数理モデルで考えるために下のような表で考えました。

そして、男性1〜3までの「青葉」を好きになる結果は下のようになります。「Yesは好きになる」 「Noは好きにならない」です。
<表1>

男性1(X1) 男性2(X2) 男性3(X3) 合計
No No No 0
Yes No No 1
No Yes No 1
No No Yes 1
Yes Yes No 2
Yes No Yes 2
No Yes Yes 3
Yes Yes Yes 3

そして、確率変数(X1〜X3)に関して、X1とX2を抽出して1: 好きになる確率 0: 好きにならない確率を表にしたのが下のものです。

X1 X2
0 1 0 1 実験値
1/2 1/2 1/2 1/2 確率

これらをパターン分けして見ると下のようになります。

X1 X2 X1 + X2
0 0 0
1 0 1
0 1 1
1 1 2

独立した確率変数を足し算して見た結果もともと4パターンあったものが3パターンに減っています。

つまり、

X1, X2の独立下確率変数を1つの塊としてみる

と言うことが「確率変数の足し算」と言う意味です。
これはどう言うことかと言うと

「男性1が好きになり、男性2が好きにならない」という事象と「男性2が好きになり、男性1が好きにならない」という事象は「同時に起きない」

のでこのようなことを「排反事象」と呼ぶ。

そして上の<表1>を元に実験値と確率の表を作成すると。。。

パターン数が1のもの(合計が0 or 3)

① P(X1 + X2 + X3 = 0) = P(X1=0, X2=0, X3=0) = P(X1=0)P(X2=0)P(X3=0) = 1/2 x 1/2 x 1/2 = 1/8

②P(X1 + X2 + X3 = 3) = P(X1=1, X2=1, X3=1) = P(X1=1)P(X2=1)P(X3=1) = 1/2 x 1/2 x 1/2 = 1/8

パターン数が2のものは合計が(2になるもの)

③ P(X1 + X2 + X3 = 2) = P(X1=1, X2=1, X3=0) 
+ P(X1=0, X2=1, X3=1)
+ P(X1=1, X2=0, X3=1)

= P(X1=1)P(X2=1)P(X3=0) 
+ P(X1=0)P(X2=1)P(X3=1)
+ P(X1=1)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

パターン数が3のもの(合計が1)

④P(X1 + X2 + X3 = 1) = P(X1=1, X2=0, X3=0) 
+ P(X1=0, X2=1, X3=0)
+ P(X1=0, X2=0, X3=1)

= P(X1=1)P(X2=0)P(X3=0)
+ P(X1=0)P(X2=1)P(X3=0)
+ P(X1=0)P(X2=0)P(X3=1)
= 1/8 + 1/8 + 1/8 = 3/8

これらを表にすると
<X1 + X2 + X3>

実現値 0 1 2 3
確率 1/8 3/8 3/8 1/8

ここまでの作業(計算)で「確率変数を作った」ことになります。

まとめ

こんな感じで物事に意味をもたせて「例」を作るというところが「確率変数の足し算」でキモになる内容でした。
しかし、プログラムに落とすところまでなかなか届きませんなぁ・・・
でわでわ。。。



数学への挑戦 第二弾〜卒業までに彼氏ができる確率:数理モデルxプログラミング〜

始めに断っておきますが、参考にしている書籍のタイトルです。自分の話ではございません(笑)

余談

世間にはオープンデータを始め色々な情報(統計データ)が落ちています。
図書館やインターネットには国、市が作成したという系データというものがWebAPIという形で使用することができます。
例えば、Macユーザーの方だったらターミナルを立ち上げて
下のようなコマンドを叩いてみてください。
curl -s https://api.ipify.org?format=jsonこれをターミナルから叩くと、自分の端末が使用しているグローバルIPがわかるらしいです。

こんな感じで、たくさんの情報がインターネット上にあるのでそれを有効利用するために「統計」「人工知能」。。。などと騒がれる昨今ですが、基本を理解しないと「なんとなく動いた。。。」で終わってしまうんで基本を理解つまりは数学的にどういう意味なのか?を理解するために数理モデルを学習します。

学習中の本は以下のものです。

彼氏ができる確率

この本に出てくる「青葉」は女子大生です。やはり女の子は結婚などがきになるようです。
そして、結婚できるか不安になったようです。。。

その不安を解消するために「数理モデル」をしようしようというのが今回のお話です。。。

ベルヌーイ分布

「なぜ?分布が?」と思った方、自分もそう思ったのでよく本を読んでみます。
とりあえずは「確率」でものを考えるようです。
コインと時と同じように考えますので。。。
「出会った男性が青葉のことを好きになる or ならない」で考えます。

好きになる 好きにならない
1 0

そして、確率変数の時と同じように表にすると下のようになります。

出来事 確率
好きにならない 0 1 - p
好きになる 1 p

P(X1 = 1) = p
P(X2 = 0) = 1-p

これが、ベルヌーイ分布というもだと書いてありました。

確率変数Xが、「確率pでX=1」となり、「確率1-pでX=0」となる時、確率変数Xはベルヌーイ分布に従う、という

これをベースにして

n人の異性と出会いx人から好かれる確率を計算する

ここで人数を「n」とか「x」のように<変数>にしておくとこの変数に10とか100とか入れ替えて計算できる、ということです。
プログラマからして見ると「いつも使ってるものと同じ」です。
データ型はintとかlongになるのかな?いや、小数点も扱うからdoubleかもしれない(笑)

そして、上の値は○○%の確率で「好きになる」 or 「好きにならない」の2択であることに注意が必要です。
さらに、「確率」と記載していますが、これは「割合」を示す数値で例えば『「確率p=0.01」で男性に好かれる』というのは100人と出会った場合男性が一人好きになるという意味なので確率というよりも「割合」という意味になります。

実際に考える

男性3人に出会いそれぞれが青葉を好きになる結果のパターン数を出してみる

表にして見ると下のようになります。あくまで人数に注目しています。

男性1(X1) 男性2(X2) 男性3(X3) 合計
No No No 0
Yes No No 1
No Yes No 1
No No Yes 1
Yes Yes No 2
Yes No Yes 2
No Yes Yes 3
Yes Yes Yes 3

このようになります。「Yes」は好きになる、「No」は好きにならないことを示しています。

そして「青葉」が気がついたことは下のようなことです。

好きになる人の合計は常に「X1 + X2 + X3」になる

なるほど、「男性1〜3」を変数として考えればそーなるな。。。

独立な確率変数

当然の話ではあるが、男性1〜男性3に関連性は、ありません。このような状態を「独立」していると言いいます。

確率変数が独立であるというのは、どんな実験値x1, x2についてもP(X1 = x1, X2 = x2) = P(X1 = x1)P(X2 = x2)が成り立つ

つまり、上のベルヌーイ分布に照らし合わせ流と下のようになります。

P(X1 = 0, X2 = 0) = P(X1 = 0)P(X2 = 0)
P(X1 = 0, X2 = 1) = P(X1 = 0)P(X2 = 1)
P(X1 = 0, X2 = 1) = P(X1 = 0)P(X2 = 1)
P(X1 = 1, X2 = 0) = P(X1 = 1)P(X2 = 0)
P(X1 = 1, X2 = 1) = P(X1 = 1)P(X2 = 1)

そして、実験値と確率を表にすると下のようになります。

X1 X2
0 1 0 1 実験値
1/2 1/2 1/2 1/2 確率

X1の期待値は

(0 x 1/2) + (1 x 1/2) = 0.5

X2の期待値は

(0 x 1/2) + (1 x 1/2) = 0.5

両方とも同じになります。

今日はここら辺にしておきます。次回は「確率変数の足し算」をやります。

でわでわ。。。



数学への挑戦 第二弾〜期待値と分散:数理モデルxプログラミング〜

今回は、期待値に関して学習します。
前回は、確率変数について学習しました。具体的に記載しませんでしたが、確率変数は実現値でもありました。

学習中の本は以下のものです。

サイコロの場合

目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

期待値

期待値=<確率変数の実現値> x <実現値の確率>の合計

つまり、サイコロの期待値は・・・

(1 x 1/6) + (2 x 1/6) + (3 x 1/6) + (4 x 1/6) + (5 x 1/6) + (6 x 1/6) = 3.5となる。

傘を持ってくるこないの話では

始めにやった損失も同様に期待値を比較するものになります。

これの場合は下のような表を使いました。

傘を持ってくる 持ってこない
Ⅰ 晴れ(0.4 : -2) Ⅲ 晴れ(0.4 : 0)
Ⅱ 雨(0.6 : -2) Ⅳ 晴れ(0.6 : -10)

なので上のケースに当てはめると
傘を持ってくる場合:(0.4 x -2) + (0.6 x -2) = - 0.2
傘を持ってこない場合:(0.4 x 0) + (0.6 x -10) = - 6

(A) 傘を持ってくるときの「期待値」は -2
(B) 傘を持ってこないときの「期待値」は -6
つまり、(A) > (B)が成り立つので(A)の方が得という判断になる。

計算式

一般化して(変動する値を文字に置き換えて)式を書くと
期待値:E[X] = xi pi
というような形になります。

分散

(実現値 - 期待値)^2(2乗)の平均
この文言では意味がわからないので、サイコロの場合で考えると

目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

期待値=3.5

(1 x 1/6) + (2 x 1/6) + (3 x 1/6) + (4 x 1/6) + (5 x 1/6) + (6 x 1/6) = 3.5

上の定義に当てはめると ※「^」キャレットは〜乗の意味
(1 - 3.5)^2 + (1 - 3.5)^2 + (2 - 3.5)^2 + (3 - 3.5)^2 + (4 - 3.5)^2 + (5 - 3.5)^2 + (6 - 3.5)^2 = 2.9 ...
なので分散は2.9.119...となる

これを一般化すると下のようになる。期待値は「u」とする
分散値:V[X] = (xi - u)^2 pi

とりあえずはこんなものだというところの理解(思い出したい時にこの記事を見るレベル)で良いようです。(本にそう書いています)

ちなみに、プログラムを書いていないですが、用途が決まらないのでまだコードには落とせませんでした。。。

でわでわ。。。



数学への挑戦 第二弾〜確率変数:数理モデルxプログラミング〜

前回は、集合を使って数理モデルを作成しました。
目的は「喫煙者のいる割合を求める」と言うところでした。

今回は上で学習したことを数学的な見地で見直します。

学習中の本は以下のものです。

確率変数

前回の話では、コインの表裏を使ったので下のような確率が存在します。

出来事 確率
裏が出る 0 0.5(1/2)
表が出る 1 0.5(1/2)

そして、出来事の集合をΩ={裏, 表}のように表現します。
さらに、(わかりやすいように)コインがちょっと曲がっていて上の確率が変わり下のようになったとします。(仮定)

出来事 確率
裏が出る 0 0.4
表が出る 1 0.6

ここでの「0」「1」が確率変数というものになります。

サイコロの場合

目の数 1 2 3 4 5 6
確率 1/6 1/6 1/6 1/6 1/6 1/6

1〜6が確率変数で下のように数式で表します。
1(実現値) x 1/6(確率)

そして一般化するとE[X] = xi pi
のように表現できる。

ということでした。

でわでわ。。。



数学への挑戦 第二弾〜集合を使う:数理モデルxプログラミング〜

前回は「傘を持って行くか行かないか?」をテーマに数理モデルを考えました。

今回は、数理モデルでの喫煙率を求める方法を考えます。
参考にする本は下のものです。

前提

この本に登場する「青葉」が担当することになった大学内の喫煙率調査を行う場合の内容で考えていきます。前提としては

  1. 大学内は禁煙
  2. 生徒数は1000人
  3. 下のような質問(アンケート)をしても適切な答えは返ってこない
    あなたは学内でタバコを吸ったことがありますか?
    <はい> <いいえ>
    どちらかに丸をつけてください

このアンケートを見てもう一人の登場人物「花京院」がダメ出しをして以下のような手順で「喫煙率」を求めようと言うことになった。
こんな内容で書かれていました。

行ったことの一覧

  1. 回答のランダム化
  2. 集合で考える
  3. 期待値と分散
  4. 結論を見る

数理モデルを作る

1.回答のランダム化

学内で「違反行為」に当たる喫煙を行なったのか?と言う質問に対して全員が正直に「YES」と答えるとは考えにくいので「回答のランダム化」を行います。
早い話が、「大数の弱法則」を使用して「確率によってバラツキの出る値を0に近づける」=「確率(パーセンテージを含む)を無視できるレベルまで下げる」と言うことを行いアンケートの結果をまとめると言うことです。

具体的に①

コインを投げてもらい、裏が出たら必ず<はい>を選択してもらう

この方法で、正直に答える人とそうでない人の割合(確率)を求めることで「正直に答えない人=喫煙者」の割合を求めると言うことです。

2.集合で考える

まずはグループわけを行います。下のように分けます。

  1. Aグループ = コインで表が出た人
  2. Bグループ = コインで裏が出た人
  3. Cグループ = Aの中でタバコを吸った人
  4. Dグループ = Bグループでタバコを吸った人

<図1>

喫煙率の推定

アンケートの結果で<はい>と答えた人が600人いたと仮定すると下のようになる。

Cグループ = コインの表が出て、正直に<はい>と回答
Bグループ = コインの裏が出て<はい>と回答

<はい>と回答した人の中には上のような人が含まれますので|B U C| = 600と表現できます。
BまたはCの要素数 = 600と言う意味です。

そして「生徒数=1000」でコインの裏が出る確率は「1/2」なので|A|=500, |B|=500と推測することができる。確定ではないので注意です。

上記の情報をまとめると以下のようになる。
|B U C|=600, |A|=500, |B|=500
そして、コインの表裏はランダムに決まるので「確率的に」以下のようになる
|C|/|A| = |D|/|B|
これは「AグループとBグループに喫煙者がX人ずついるであろう」と言う考えを基にしている

具体的に②

実際に行ってはいないけれど「仮に」喫煙者が400人いたとするのであれば、喫煙率は「400 / 1000 = 40%」になるので「コイントスでA, Bグループ(500人ずつ)にいる喫煙者社の割合(確率)も40%で200人ずついることになる。

求めるべき値の喫煙者数=400は下のようにして求めることができる。

|B U C| = |B| + |C|
|B U C| - |B|=  |C| 両辺から|B|を引く

下の値を使用して計算すると。。。
|B U C|=600, |A|=500, |B|=500
次のような計算式で求めることができる
|B U C| - |B| = |C| = 100
|C| / |A| = 100 / 500 = 0.2 = 40%
となる。。。つまり喫煙者の割合は「40%」になり「仮定」で示した「400」と言う数値も正しいものであると言える。

この結果は、喫煙率でなくても良い。

と言うことらしいです。

ここまでをプログラムに落とすなら。。。

Javaで上のものを表現する

まずは、主要な変数を明確にします。

  1. A〜Dまでのグループの人数
  2. ここで求めたい数値(喫煙率)

「上の数式そのまんま?」と思うかもしれませんが、その通りになります。
プログラムに落とし込むときに重要なのは、各パラメータの意味が重要になります。

早い話が

「数理モデルのインプットとアウトプットがなんなのか?」がわかれば良いと言うことです。
実装するメソッドも下のようになります。

/** 
 * 恋んトスによるランダム化の、割合を求める、数理モデル
 * 目的は引数に依存する
 * @param all 対象になる(分母の)数
 * @param resultValue アンケートの結果<はい>の数
 */
public double daisunoHosoku(int all, int resultValue) {
   // |B U C| 上のケースでは600だった
   double BorC = resultValue;
   // |A|
   double A = all / 2;
   // |B|
   double B = all / 2;
   // |C| / |A| = |D| / |B|で求めるのは|C|
   double C = BorC - B;
   // 割合(確率)を返却する
   return C / A;
}

と上のようになります。
ちなみに、今後このコードをカスタムしていきます。
でわでわ。。。

<!— BODY広告-->



数学への挑戦 第二弾〜実装編:数理モデルxプログラミング〜

今回は「傘を持っていくか?いかないか?」の選択を行う時の損失(気持ちを基準に)をみてどうするべきか?の判定を下す処理を実装してみようと思います。
元元の話はこちらです。

傘を持ってくか?の数理モデル

以下のような条件がありますので注意です。

<前提>
行動の選択肢は「傘を持ってくる」 or 「持ってこない」の2つ
<嫌度>
雨に濡れることの嫌度 = -10(濡れないとき = 0)
傘を持ってくることの嫌度 = -2
<確率>
雨の確率: 60% = 0.6
晴れの確率: 40% = 0.4

数理モデルの作成をするのには以下のような手順がありました。

  1. 前提になる条件を整理する(書き出す)
  2. 判定する基準を作る(今回の場合は「嫌度」です)
  3. 全部のパターンから平均の損失を求める
  4. 求めた結果、変数(確率変数)になる部分を一般化(文字に置き換える)してやる
  5. 上記の結果、不等式(-ac > -pc)ができるのでそれが数理モデルになる。

数理モデルを作る

プログラムでも、数学でもこの部分は同じようで、まずは頭の中でロジックを作成します。→「理論的に、こーなる!」を作成する

「傘を持ってくるか?」の話では、上の条件より上の条件より以下のような式になります。

<実際の値を計算する>
この記事の「2.平均的な損失を求める」より

「確率」と「その確率で実現する値」の積の合計を平均的な損失と定義する

このような記述がこの本にはありました。

そして、上の部分がわかりづらいので「早い話が。。。」の形にすると下のようになります。

雨が降ったが傘を持っているときは「確率」x「嫌度」=-0.8 ...になる

というわけで式にすると。。。傘を持ってきた場合は
(0.4 x -2) + (0.6 x -2) = -2
となるので「傘を持ってきた時の平均的な損失は−2」

対して、傘を持ってこなかった場合は。。。
(0.4 x 0) + (0.6 x -10) = -6
となるので「傘を持ってこなかった時の平均的な損失は-10」となる。。。

なるほど、しかし上の式で平均になるのか?
平均は「全部の値を大してその個数でわる」ものなので。。。

傘を持ってくる 持ってこない
Ⅰ 晴れ(0.4 : -2) Ⅲ 晴れ(0.4 : 0)
Ⅱ 雨(0.6 : -2) Ⅳ 晴れ(0.6 : -10)

上の表からして、上の全パターンを計算してその合計を出してそのパターン数(4)で割ってやれば良いことになる。。。がしかし、上の記述ではそんなことをしていないのがきになる。。。が比較するから割らなくても問題ないのか?

そんなわけで、次のステップ

変数になるものを指定する

上の表からして、変わる値はほぼ全部かな?

  • 「降水確率」は日によって変わる = p
  • 「嫌度」もその日の気分で変わる = c

これらを変数として「p」「c」とする、そしてこのケースでは必ず「0 < p < 1」(パーセントなので)、「マイナスの値」(嫌度なので)となるから

降水確率60% = 0.6 = p : 晴れの確率40% = 1 - p
雨に濡れる嫌度 = -10 = -c : 傘を持ってくる嫌度 = -c/5

今までのをまとめると。。。

雨の場合
(0.4 x -2) + (0.6 x -2) = -2 => ((1-p) x -2) + (p x -2) = (-2 + 2p) + (-2p) => 平均は「-2」
晴れの場合
(0.4 x 0) + (0.6 x -10) = -6 => ((1-p) x 0) + (p x -10) = 0 + -10p = 平均は「-10p」

ここで「雨に濡れる嫌度が1/5」になっているのでこれも変数化します。変数名は「a」にします、そして割合なので0 < a < 1」になります。まとめると以下のようになります。

雨の確率 = p : 晴れの確率 = 1 - p
雨に濡れる嫌度 = -c : 傘を持ってくる嫌度 = -ac

これを式にすると。。。

傘を持って来た時
((1-p) x -ac) + (p x -ac) = (-ac + pac) + (-pac) = -ac
傘を持ってこなかった時
((1-p) x 0) + (p x -c) = (0 - pc) = -pc

なので傘を持ってくる条件は「-ac < -pc」 => 「a < p」
つまりは、「雨の確率がa(傘を持ってくる嫌度の割合)より大きい時」ということになります。

プログラムにしてみる

つまるところは「数式」の意味がわかっていれば良いので、数理モデル=数式の計算結果を返してやれば良いことになりますので。。。

   /**
     * 傘を持ってくる、持ってこない時の行動を判断する時の数理モデル実装
     * 
     * @param rainy 降水確率
     * @param bring 傘を持ってくる嫌度
     * @return true=傘を持ってくる : false=持ってこない
     */
    public boolean bringKasa(double rainy, double bring) {
        return bring < rainy;
    }

となります。

でわでわ。。。