Thymeleaf Layout Dialectのth:withに関するエラー

バグなのか仕様変更なのか後で調べるためのメモ。バージョンアップ後から下記のような使い方するとエラーが発生する様になった。

user.html
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    layout:decorate="~{templates/layout}"
    th:with="currentMenu = ${param.from} != null and ${param.from[0]} == 'list' ? 'admin' : 'userSaveForm'">
layout.html
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    th:with="lang = ${#locale.language}"
    th:lang="${#locale.language}">
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as assignation sequence: "currentMenu=(((${param.from} !,lang=${#locale.language}" (template: "templates/layout" - line 5, col 5)

user.htmlのth:withを単純な代入式にすると、エラーにならない。

th:with="currentMenu = 'admin'"

Token authentication requirements for Git operations

Githubから以下のようなメールが届いた。どうやら、2021/8/13でパスワードによる認証が出来なくなるらしい。

[GitHub] Deprecation Notice
Basic authentication using a password to Git is deprecated and will soon no longer work.
※詳しくはこちらのURLを参照。

当方ではEclipseでpush/pullするときにパスワード認証を使用しているので、Token authenticationを使用するように変更する。(Jenkinsでパスワード認証を使用している場合も同様の設定が必要になる)

Github側の設定

  1. Settings > Developer settingsのPersonal access tokensを開き、Generate new tokenをクリックする。
  2. 必要な権限にチェックを入れ、Generate tokenをクリックする。
  3. 作成されたtokenをコピーしておく。

Jenkins側の設定

  1. プロジェクトの設定画面を開き、認証情報の追加をクリックする。
  2. 先ほどコピーしたTokenをパスワードに入力する。

Eclipse側の設定

  1. 先ほど生成したTokenをパスワードに入力する。

Eclipse起動構成の移行方法

起動構成のエクスポートは実行構成のウィンドウにボタンがあるので分かりやすかったのだが、インポートが分かりづらかったので、メモを残しておく。

エクスポート方法

1.メニューの実行>実行構成をクリックする。
2.左上のエクスポートボタンをクリックする。

3.保存先、エクスポート対象を選んで完了をクリックする。

インポート方法

1.メニューのファイル>インポートをクリックする。
2.インポート・ウィザードから起動構成を選択して、次へをクリックする。

3.起動構成を保存してあるフォルダを選択し、インポート対象を選び完了をクリックする。

分類問題を機械学習で解く

今回の目的

理論とか細かいことは後回し、取り敢えず実行してみて、機械学習がどのようなものか感じをつかむ。

分類問題とは

データを複数のクラスに分類すること。

今回は、機械学習の手法の一つである教師あり学習を使って分類する。教師あり学習とは、予め用意された問題と正解の傾向を学習することで、未知の問題に対する正解を推測する手法をいう。

必要なもの

  • データセット
  • 分類器 (データを分類する機械学習モデル)
    • k-近傍法(k-NN)
    • 決定木
    • サポートベクターマシン(SVM)
    • ロジスティック回帰など

データの傾向を学習させる必要があるため、目的に合わせたデータセットを事前に用意する。分類器はライブラリとして既に実装されているものを利用する。

機械学習を試すとき、まずはデータを準備することが一つのハードルになるが、scikit-learnにはいくつかの標準的なデータセットが付属しているので、自分で用意しなくても試すことが出来る。

今回はsklearn.datasetsのload_iris(アヤメの花のデータセット)を使用する。がくや花びらの大きさとアヤメの種類がデータに含まれていて、がくや花びらの大きさからアヤメの種類を予測する。

Pythonで実装

from sklearn.datasets import load_iris

iris = load_iris()
# データの内容を確認する
iris
{'DESCR': '(データの説明は省略)',
 'data': array([[5.1, 3.5, 1.4, 0.2],
        [4.9, 3. , 1.4, 0.2],
        [4.7, 3.2, 1.3, 0.2],
        [4.6, 3.1, 1.5, 0.2],
        [5. , 3.6, 1.4, 0.2],
        (中略)
        [5.9, 3. , 5.1, 1.8]]),
 'feature_names': ['sepal length (cm)', # がくの長さ
  'sepal width (cm)',                   # がくの幅
  'petal length (cm)',                  # 花びらの長さ
  'petal width (cm)'],                  # 花びらの幅
 'filename': '/usr/local/lib/python3.6/dist-packages/sklearn/datasets/data/iris.csv',
 # アヤメの種類 0: 'setosa', 1: 'versicolor', 2: 'virginica'
 'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]),
 'target_names': array(['setosa', 'versicolor', 'virginica'], dtype='<U10')} 

この後のデータの解析を行いやすくするため、pandasのDataFrameに変換する。

import pandas as pd

# DataFrameに変換する
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['target'] = iris.target_names[iris.target]

# 先頭5行を表示する
df.head()
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)target
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa

ざっとデータの内容を確認する。欠損値もないしそのまま使えるように既に整えられている。

df.info()

RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   sepal length (cm)  150 non-null    float64
 1   sepal width (cm)   150 non-null    float64
 2   petal length (cm)  150 non-null    float64
 3   petal width (cm)   150 non-null    float64
 4   target             150 non-null    object 
dtypes: float64(4), object(1)
memory usage: 6.0+ KB
df.describe()
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)
count150150150150
mean5.8433333.0573333.7581.199333
std0.8280660.4358661.7652980.762238
min4.3210.1
25%5.12.81.60.3
50%5.834.351.3
75%6.43.35.11.8
max7.94.46.92.5
df['target'].value_counts()

virginica     50
setosa        50
versicolor    50
Name: target, dtype: int64

次に説明変数と目的変数に分ける。
説明変数とは目的変数を説明する変数のこと。これをもとに予測する。
目的変数とは予測したい変数のこと。

# 説明変数
X = df.drop('target', axis=1)
# 目的変数
y = df['target']

さらに、トレーニング用データセットとテスト用データセットに分ける。未知の値について予測する性能をテストするため、テスト用のデータはトレーニングで使用してはいけない。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

分類器にはサポートベクターマシンを使用する。scikit-learnサポートベクターマシンを実装したライブラリがあるので、それをそのまま使用する。

from sklearn.svm import SVC

svc = SVC()
# 問題と正解の傾向を学習させ、学習済みモデルを作成する
svc.fit(X_train, y_train)

学習済みモデルが作成出来たら、テストデータを使ってアヤメの種類を予測してみる。

svc.predict(X_test)

array(['virginica', 'versicolor', 'setosa', 'virginica', 'setosa',
       'virginica', 'setosa', 'versicolor', 'versicolor', 'versicolor',
       'virginica', 'versicolor', 'versicolor', 'versicolor',
       'versicolor', 'setosa', 'versicolor', 'versicolor', 'setosa',
       'setosa', 'virginica', 'versicolor', 'setosa', 'setosa',
       'virginica', 'setosa', 'setosa', 'versicolor', 'versicolor',
       'setosa', 'virginica', 'versicolor', 'setosa', 'virginica',
       'virginica', 'versicolor', 'setosa', 'virginica'], dtype=object)

どのくらい正解しているのかは下記で確認出来る。

svc.score(X_test, y_test)

0.9736842105263158

97%正しいアヤメの種類を予測出来ている。

まとめ

上記はかなり単純な例です。このように高い率で予測出来ているのは、使用しやすく既にデータが整備されていたためです。本来データには欠損値であったり、ノイズであったり、そもそも予測するための説明変数が不足していたりしていますので、まず学習で使用するデータの作成に時間がかかります。
また、分類器も今回はサポートベクターマシンを使用しましたが、最適な分類器ではないかもしれません。どの分類器が最適か探すこともあるでしょうし、そのパラメーターのチューニングも必要になるかもしれません。
これらを詰めていき正解率を上げていく作業はなかなか楽しいです。興味があればさらに詳しく調べてみてください。

Recommendation Systemを考える

以下の機械学習の勉強の過程で小説の特徴を抽出することは出来た。ここからユーザーにおすすめの小説を推薦するにはどのような仕組みが必要なのか考える。

小説を読もうの累計ランキングをDoc2Vecで解析する その5

Recommendation System(推薦システム)とは

過去の行動をもとに、あるアイテムを好む可能性を予測するシステム。
例えば、Netflixでは、映画を見たり、投票したりするような過去の行動に応じて、新しい映画を提案している。
新しいアイテムを推奨するという点が重要となる。

・ユーザーベースの推薦システム

自分の経験と他の人の経験を組み合わせて推薦する。ユーザ間の類似度を計算し、類似度の高いユーザーが好む作品の中でまだ見ていない作品を推薦する。

このシステムを実現するには複数のユーザー情報が必要になるため、今回は不採用。

・アイテムベースの推薦システム

類似のユーザを見つけるのではなく、映画や物などのアイテムを比較する。アイテム間の類似度を計算する。

・どのような推薦システムを作成するか

ユーザーが入力した小説に似ている小説を推薦するシステムは以前作成したDoc2Vecのモデルを使用すれば実現可能である。しかし、このシステムではユーザーが毎回小説を入力しなければいけない点が煩わしい。

例えば、最近投稿された小説の中から自分の好みに合う小説があったら、自動的に通知が来るようなシステムであると良い。

このシステムは以前作成したモデルのみでは実現不可能であり、さらに自分の好みを学習させる必要がある。これまでと違い教師あり学習になるので、どのような手法があるか調べるところから始めることにする。

Recommendation Systemを考える その2へ続く。

GreenMail Ver. 1.6 Migration

GreenMailを1.6にバージョンアップするとAssertionErrorが発生する場合は、 以下の依存関係が悪さをしているので、

    <dependency>
      <groupId>com.sun.mail</groupId>
      <artifactId>javax.mail</artifactId>
    </dependency>

以下の様に変更すれば良い。

    <dependency>
      <groupId>com.sun.mail</groupId>
      <artifactId>jakarta.mail</artifactId>
    </dependency>

Ver. 1.6から依存関係にあるjavamailが変更された。

小説を読もうの累計ランキングをDoc2Vecで解析する その5

小説を読もうの累計ランキングをDoc2Vecで解析する その4の続き。

形態素解析をする前に正規化処理を追加した。それ以外には類似文章の検索結果が良くなるように、文章数と1文章当たりの文字数、次元数などを調整した。
その代わり類似単語の検索については悪化しているように感じる。

追記(2020/09/16):
指定したURLの小説の類似小説を表示する関数を追加した。

修正版 (2020/09/16):

TensorflowからNVIDIAのGPUを使用する(Windows)

使用しているGPUがCUDAに対応していることを確認する

https://developer.nvidia.com/cuda-gpus#compute
上記サイトの一覧に自分のGPUがあることを確認する。

Build Tools for Visual Studio 2019をインストールする

https://visualstudio.microsoft.com/ja/downloads/
上記のページにアクセスし、Visual Studio 2019 のツールからBuild Tools for Visual Studio 2019をダウンロードする。
以下のC++ Build Toolsにチェックを入れてインストールする。それ以外はデフォルトで良い。

CUDA Toolkitをインストールする

https://developer.nvidia.com/cuda-toolkit-archive
上記のページにアクセスし、CUDA Toolkitをダウンロードする。
必ずTensorflowが動作保証しているバージョン(https://www.tensorflow.org/install/gpu)をダウンロードすること。最新バージョンではDLLが見つからないなどエラーが発生し、動作しない可能性が高い。
今回はTensorflow 2.3.0を使用するため、CUDA Toolkit 10.1 update2 (Aug 2019)をダウンロードする。

インストーラーを起動して以下のオプションを指定する。それ以外はデフォルトで良い。

cuDNNをインストールする

https://developer.nvidia.com/cudnn
上記のページにアクセスし、cuDNNをダウンロードする。(ダウンロードは無料だが、ユーザー登録が必要)
今回はTensorflow 2.3.0、CUDA Toolkit 10.1を使用するため、cuDNN v7.6.5 (November 5th, 2019), for CUDA 10.1をダウンロードする。

ダウンロードしたファイルを解凍し、CUDAをインストールしたフォルダに上書きする。

動作確認

Tensorflowを実行し以下の通りGPUが読み込まれていることを確認できた。

2020-08-18 19:54:11.658397: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library nvcuda.dll
2020-08-18 19:54:11.895033: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1716] Found device 0 with properties: 
pciBusID: 0000:01:00.0 name: GeForce GTX 1070 computeCapability: 6.1
coreClock: 1.7715GHz coreCount: 15 deviceMemorySize: 8.00GiB deviceMemoryBandwidth: 238.66GiB/s
2020-08-18 19:54:11.895468: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cudart64_101.dll
2020-08-18 19:54:11.924128: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cublas64_10.dll
2020-08-18 19:54:11.955523: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cufft64_10.dll
2020-08-18 19:54:11.962251: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library curand64_10.dll
2020-08-18 19:54:11.989806: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cusolver64_10.dll
2020-08-18 19:54:12.003706: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cusparse64_10.dll
2020-08-18 19:54:15.670393: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library cudnn64_7.dll
2020-08-18 19:54:15.670725: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1858] Adding visible gpu devices: 0

Pythonの実行環境構築(Windows)

Windows上でPythonの実行環境を構築する。

  1. PleiadesからPythonのFull Editionパッケージをダウンロードし任意のフォルダに解凍する。
  2. pipの公式サイトからget-pip.pyをダウンロードし任意のフォルダに保存する。
  3. Pleiadesに同封されているPythonでget-pip.pyを実行する。 <PLEIADES_INSTALL_DIR>\python\3\python get-pip.py
  4. Tensorflowなどインストールしたい場合には、eclipseの「ウィンドウ(W) > 設定(P) > PyDev > インタープリーター > Pythonインタープリーター > Python3」を開き「Manage with pip」ボタンをクリックし、以下の画面の様に入力実行する。

TensorflowでNVidiaのGPUを使用する場合は別途CUDA Toolkitなどのインストールが必要になるはずで、それについては後で試してみる。