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メソッドは省略して書いているので適宜付与してもらうとよいだろう。

  1. public class Student {  
  2.   int id;  
  3.   String name;  
  4.   Result[] result;  
  5. }  
  6.   
  7. public class Result {  
  8.   String course;  
  9.   int score;  
  10. }  

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

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

  1. <mapper namespace="mapper.student">  
  2.   <resultmap id="student" type="student">  
  3.     <id column="id" property="id" />  
  4.     <result column="name" property="name" />  
  5.   
  6.     <collection property="result" oftype="Result">  
  7.       <result column="course" property="course" />  
  8.       <result column="score" property="score" />  
  9.     </collection>  
  10.   </resultmap>  
  11.   
  12.   <select id="find" resultmap="student">  
  13.     SELECT id, name, course, score  
  14.     FROM student, result  
  15.     WHERE id = refid  
  16.     ORDER BY id  
  17.   </select>  
  18. </mapper>  

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

SELECTの結果

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

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

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

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



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

2020年4月23日木曜日

機械学習と深層学習

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

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

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

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

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