2020年4月29日水曜日

MyBatisでヘッダ明細型のデータを扱う

「ヘッダ明細型」のデータはアプリを作るうえでよく登場するデータ構造である。 「ヘッダ」が親データ、「明細」が親に紐づく子データを表しており、例えば成績のデータなどで、各生徒の英語と数学の成績を表す場合に生徒の情報を親としてヘッダテーブルに格納、成績情報は親にidで紐づけて明細テーブルに格納すると以下のようにあらわすことができる。

studentテーブル(ヘッダ)

id name
100 やまだ
101 たなか

resultテーブル(明細)

refid course score
100 英語 80
100 数学 90
101 英語 50
101 数学 68

やまだ君の成績は英語80点で数学90点。たなか君の成績は英語50点で数学68点を表している・・・たなか君はもう少し頑張ったほうがいいですね・・・

このようなデータの持ち方は「Summary」と「Detail」などとも呼ばれたり、呼び方はさまざまであるが、商品カートや伝票など業務の世界でも頻繁に登場する。

このようなデータを扱う場合はStudentクラスがResultクラスのオブジェクトを持つようなネストした構造で表現することができる。 例えばJavaの場合のクラス定義は以下のようになる。setter/getterメソッドは省略して書いているので適宜付与してもらうとよいだろう。

public class Student {
  int id;
  String name;
  Result[] result;
}

public class Result {
  String course;
  int score;
}

ここでMyBatisを使ってstudentテーブルとresultテーブルの内容を上記クラスに読み込むことを考えてみる。studentテーブルをSELECTしてからresultテーブルをSELECTするように2つのSELECTに分けてもよいが、MyBatisではテーブルを結合した1つのSQLでネストしたクラスを読み込むことができる。

mapperでcollectionタグを使いネストした部分を定義する。property属性に子オブジェクトを格納するプロパティ名、oftype属性にそのクラス名を指定する。 SELECTのSQLでは2つのテーブルを結合する。

<mapper namespace="mapper.student">
  <resultmap id="student" type="student">
    <id column="id" property="id" />
    <result column="name" property="name" />

    <collection property="result" oftype="Result">
      <result column="course" property="course" />
      <result column="score" property="score" />
    </collection>
  </resultmap>

  <select id="find" resultmap="student">
    SELECT id, name, course, score
    FROM student, result
    WHERE id = refid
    ORDER BY id
  </select>
</mapper>

SELECTの結果は以下のようにstudentの内容とresultの内容が1行に結合されたものとなるが、親クラスの内容はmapperのidタグで指定された列でまとめられオブジェクトが構築されるようである。

SELECTの結果

id name course score
100 やまだ 英語 80
100 やまだ 数学 90
101 たなか 英語 50
101 たなか 数学 68

以下のコードで読み込みを行うと・・・

List<Student> entities = sqlSession.selectList("mapper.student.find");

下図のようなオブジェクトとして読み込まれる。



使いこなせば複雑なデータ構造をシンプルに扱えそうな方法であるが、実際使ってみると気を付けなければならない点もあり、そのような点は次回以降また紹介していこうと思う。

2020年4月23日木曜日

機械学習と深層学習

「機械学習と深層学習って何が違うの」という質問を受けることが良くあるが、その説明としてこの図がわかりやすいのかなと思う。

「機械学習」というのは、何らかのパターンを自動で覚えて、次に何らかのパターンが発生したときに、過去に覚えたパターンと近いかどうかを判別したり、次にどういうパターンになるかを予測するようなプログラムのこと。
パターンというのは、例えば画像だったり、文字列だったり、株価の毎日の変動だったり。例えば、犬の画像をたくさん覚えた機械学習に動物の写真を入力すると犬かどうか判別したりできるし、株価のデータを入力すると次の日に上がるか下がるかを過去のパターンから予測してくれるようになる。 自動で覚えてとは書いたが人がそれらのデータを集めて機械学習のプログラムに覚えさせてもいいと思う。

一方で「深層学習」とは「ディープラーニング」や「ディープニューラルネットワーク(DNN)」とも呼ばれるが、機械学習をするための一つの手法のこと。これのベースになっている「ニューラルネット」という技術は神経細胞に似た網目構造を使って計算する方式で何十年も前から知られていて、網目構造を増やす(層を深くする)と性能が上がることはわかっていた。しかし昔はコンピューターが非力だったので少し増やすと計算が終わらず使い物にならなかったのが、最近はまともに動くようになってきて性能も高く実用的になったので一気に知名度が上がってきたというものである。

ただ、深層学習は一気に知名度が上がったので、世の中的には機械学習=深層学習と見てしまわれることが多い。そんな感じで冒頭の質問をされた時には、ちょっと古いが、ヘッドホンステレオ=ウォークマンと同じイメージと説明している。

深層学習の中にも層の作り方やデータの処理の仕方でいろいろな方法があって、画像判定が得意とか、予測が得意とか、用途に応じて使い分けられている。 例えば、最後に紹介するDEEPという深層学習では文章を解析して分類することができるものとなっていて、ここの研究論文にあるような飲食店のレビュー文章を分析することをしている。

2018年1月18日木曜日

BATファイルでエラー出力(引数チェックなど)

Windowsのバッチファイルでエラーメッセージを標準エラー出力に出す方法。以下で"ERROR!!"が標準エラー出力に出るようになる。
echo ERROR!! 1>&2
例えば以下のように書いておけば、バッチの引数がなかった時にエラーメッセージを出してエラーレベルを1にして終了する。
if "%1"=="" (
  echo Usage: mybat.bat {param}... 1>&2
  exit /b 1
)
実行結果
C:\>mybat.bat
Usage: mybat.bat {param}...

C:\>echo %ERRORLEVEL%
1

2017年12月21日木曜日

ApacheでHTTPSを通すフォワードプロキシ

XAMPPのapache2.4でhttpsを通すフォワードプロキシを構築。今どきのサイトはほとんどがhttpsになっている。httpを通すことができる設定はいろいろなところに載っているがhttpsだと追加設定が必要で嵌ったのでメモ。 まずはxamppフォルダのapache\conf\httpd.confでプロキシに必要なモジュールを有効に。 mod_proxyとmod_proxy_httpだけじゃなくて、mod_proxy_connectも有効にするのがポイント。
...
LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule proxy_express_module modules/mod_proxy_express.so
#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
#LoadModule proxy_html_module modules/mod_proxy_html.so
LoadModule proxy_http_module modules/mod_proxy_http.so
...
次に、apache\conf\extra\httpd-proxy.confにプロキシ設定を書く。httpsを通すときはAllowCONNECTが必要。
<IfModule proxy_module>
<IfModule proxy_http_module>

# ここから
ProxyRequests On
ProxyVia On
AllowCONNECT 443

# allow request from 127.0.0.1
<Proxy *>
      Require ip 127.0.0.1/32
</Proxy>
# ここまで追加

</IfModule>
</IfModule>
これで、apacheをリスタートすればhttpsが通るフォワードプロキシとなる。 この設定では127.0.0.1からのリクエストのみ通すよう Require ip で制限をかけているのでそこは適宜読み換えてください。

2016年9月24日土曜日

Windowsでopensslを使う

Windowsでopensslコマンドを使った時に嵌ったので、今後のためにメモ。

本家のOpenSSLではソースコードのみを配布しているためちょっと使おうと思ったときには敷居が高い。 バイナリ版はいくつかあるようだが Win32 OpenSSLがx64版もありよさそうな感じである。 ここから "Win64 OpenSSL v1.1.0a" を落としてきてインストール。コマンドラインから実行すると以下のエラーが出た。

C:\> c:\OpenSSL-Win64\bin\openssl.exe req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out server.crt -keyout server.pem
Can't open C:\Program Files\Common Files\SSL/openssl.cnf for reading, No such file or directory
756:error:02001003:system library:fopen:No such process:crypto\bio\bss_file.c:74:fopen('C:\Program Files\Common Files\SSL/openssl.cnf','r')
756:error:2006D080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:81:
Generating a 2048 bit RSA private key
..................+++
..........................................................+++
writing new private key to 'server.pem'
-----
unable to find 'distinguished_name' in config
problems making Certificate Request
756:error:0E06D06A:configuration file routines:NCONF_get_string:no conf or environment variable:crypto\conf\conf_lib.c:272:

openssl.cnf というファイルが見つからないというエラーが出ている。 しかも、インストール先とは全く関係ない C:\Program Files\Common Files\SSL というフォルダを探しに行っている。

調査したところOPENSSL_CONFという環境変数にopenssl.cnfファイルの場所を指定すればよいらしいとのこと。 このファイルはOpenSSLインストール先のbin\snfフォルダにある、試しに以下のように設定して実行してみた。

C:\>set OPENSSL_CONF=C:\OpenSSL-Win64\bin\cnf\openssl.cnf

C:\> c:\OpenSSL-Win64\bin\openssl.exe req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out server.crt -keyout server.pem

---
Generating a 2048 bit RSA private key
..........................................................+++
..........................................................+++
writing new private key to 'server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Setagaya-ku
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company K.K.
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.my-company.com
Email Address []:
---

うまくいったようだ、

2016年9月2日金曜日

WindowsでUUIDを作る

プログラムを作っているとテストデータとしてUUIDを作りたいことがたまにある。 Windowsの場合、VisualStudioをインストールしていればguidgen.exeとツールが付属しているのでそれを使うことができるが、インストールしていない環境でもPowerShellを使って出力できる。PowerShellから以下のコマンドをたたく。
[System.GUID]::NewGuid().ToString()
コマンドプロンプト派の人は、PowerShellを起動するまでもなく以下で。
@powershell "[System.GUID]::NewGuid().ToString()"
ほかにはWSHを使ってもできると思うけどコマンドラインから直接できるかどうかは不明。

2016年9月1日木曜日

Bluemix CFアプリ よく使うコマンド

BluemixへのCFアプリ配備でよく使うコマンドのまとめ。

Bluemixへのログイン

IDとパスワードを入れ、スペースを選択する。そのあとスペースを選択。
cf login -a https://api.ng.bluemix.net

組織(org)-スペース(space)-アプリ(app)

のような関係になっているらしい。

スペース中のアプリ一覧

cf apps

アプリ配備

アプリの置いてあるフォルダで以下を実行。メモリは128MB割り当て。
cf push {アプリ名} -m 128M

アプリとめる

cf stop {アプリ名}

アプリの環境変数一覧

CFアプリには環境変数が設定できコードに埋め込みたくない引数などはそこに定義できる。以下で一覧を表示。
cf env {アプリ名}

環境変数を設定

以下はLINEボットを作った時の設定例。 チャネルIDなどはコードに埋め込みたくないので環境変数で設定しプログラムで読み込むようにした。
cf set-env {アプリ名} BOTAPI_CHANNEL_ID {LINEチャネルID}
cf set-env {アプリ名} BOTAPI_CHANNEL_SECRET {LINEチャネルシークレット}
cf set-env {アプリ名} BOTAPI_MID {LINE MID}

変更したら以下コマンドで反映。

cf restage {アプリ名}

動作確認

以下のURLで動作確認できる

https://{アプリ名}.mybluemix.net/

ログを見る

cf logs {アプリ名}

メモリ量変更

メモリは割り当てを64MBに変更。
cf scale {アプリ名} -m 64M

ダッシュボード

https://new-console.ng.bluemix.net/