KUINS-AirにUbuntuをEAP-TLS(クライアント証明書)を用いて接続する - GUI編

この記事は CAMPHOR- Advent Calendar の27日目の記事です。

お久しぶりです。CAMPHOR-の運営メンバーになってからはや1年半。色々やりたいことがありつつも、何も進捗を埋めていないことに焦りを感じている &es; (@_and_es) / Twitter です。あんですとお読みください。

CAMPHOR- Advent Calendar は、昨日の CAMPHOR- 2022年の総括 ~やりたいことに使ってもらえるコミュニティ~ - CAMPHOR- Blog をもって一旦締めくくられたわけですが、延長もOKということだったので記事を書いています。

何をするか

タイトルの通りです。京都大学の情報環境機構が提供している学内無線LANサービス「KUINS-Air」にUbuntuEAP-TLSを用いて接続します。GUI編ということはCLI編があるのかというと、近日中に書きたいと思っています。

EAP-TLSとは、ID / パスワードではなくクライアント証明書を用いる認証方法で、安全に接続できるため情報環境機構からも推奨されています。

Windows / macOS / iPadOS / iOS / AndroidEAP-TLSを使う方法は KUINS-Air | 無線LAN | 京都大学情報環境機構 で説明されています。でもなぜかLinuxの設定方法は書かれてないのです。Linuxを愛用する皆さんもぜひEAP-TLSを用いて安全に使いましょう!

Windows / macOS / iPadOS / iOS / Androidをお使いの皆さんも、ぜひ情報環境機構のWebサイトを見て、EAP-TLSを使いましょうね。

※この記事の内容は2022/12/26現在の情報をもとに構成されています。各種設定項目は変わることもあるため、ご自身でも情報環境機構のWebサイトを確認しながら設定することを推奨します。

環境

Ubuntu 22.04.1 LTS

Ubuntu 20.04 LTSでも同様にできたはずです。他のディストリビューションもだいたい同じようにやればできると思います。

システムの言語が英語になっているので、他の言語をお使いの方は適宜読み替えてください。

手順

KUINS-Airが利用できる場所で行ってください。

クライアント証明書を取得する

クライアント証明書申請 | クライアント証明書発行システム | 京都大学情報環境機構

⇡で説明されている手順に従い、クライアント証明書を取得します。学内限定サービスから取得するため、KUINS-Airに接続するかVPNを使う必要があります。この時点では証明書がないので、ID / パスワードを用いるPEAPを用いて接続しましょう。そのやり方は以下で説明しています。必要ない場合は読み飛ばしてください。

KUINS-AirUbuntuPEAPを用いて接続する方法

Ubuntuの設定->Wi-Fiから「KUINS-Air」を選択します。

各項目を以下のように設定します。

項目
Wi-Fi security WPA & WPA2 Enterprise
Authentication Protected EAP (PEAP)
Anonymous identity 空白
Domain rad.kuins.kyoto-u.ac.jp
CA certificate Security_Communication_RootCA2.pam1
PEAP version Automatic
Inner authentication MSCHAPv2
Username 学生アカウントのID(ECS-ID)2
Password 学生アカウントのパスワード

UsernameとPasswordは、 PandA全学生共通ポータル に入力するものと同じです。

以下の画像のようになっていればOKです。最後にConnectを押せばつながります。

EAP-TLSの設定をする

取得した証明書を用いてKUINS-Airに繋ぐ設定をします。

Ubuntuの「設定」を開き、Wi-Fiの項目を選択します。

上の手順で接続しているなど、すでにPEAPでKUINS-Airに繋げられる状態の場合は、歯車ボタンからKUINS-Airの設定に入り、Forget Connectionを押して過去の設定を削除してください。3

過去の設定を削除したら改めて「KUINS-Air」を選択し、各項目を以下のように設定します。

項目
Wi-Fi security WPA & WPA2 Enterprise
Authentication TLS
Identity 学生アカウントのID(ECS-ID)
Domain rad.kuins.kyoto-u.ac.jp
CA certificate Security_Communication_RootCA2.pam
User certificate 取得したクライアント証明書4
User private key 取得したクライアント証明書5
User key password 取得したクライアント証明書のパスワード6

以下の画像のようになっていればOKです。

最後にConnectを押して正常に接続できていることを確認すれば完了です!

あとがき

EAP-TLSを使って接続すると、ちょっと嫌なことがあっても「まあ私はEAP-TLSで認証してるしな」ってなるし仕事でむかつく人に会っても「そんな口きいていいのか?私はEAP-TLSで安全にWi-Fiを使ってる身だぞ」ってなれる。高度なセキュリティを求められる現代社会においてEAP-TLSで認証することは有効

ということで、皆さんもEAP-TLSを使いましょう。それではまたっ。


  1. Select from fileから/etc/ssl/certs/Security_Communication_RootCA2.pamを選択してください。
  2. ECS-ID(学生、非常勤講師等向け) | 京都大学情報環境機構
  3. 削除しなくても、設定画面のSecurityタブからEAP-TLSを選択することができますが、この方法だとDomainの設定ができません。過去の設定が引き継がれるのかと思いきや、実際は空白として設定されてしまうためセキュリティ上避けた方が良いでしょう。ちなみにUbuntuの設定に表示されない全ての設定項目は、nmcli connection show (接続名)というコマンドで確認できます。接続名は、Wi-Fiの場合は基本的にSSIDが設定されています。今回の場合はnmcli connection show KUINS-Airですね。
  4. ファイル名を変更していない場合は、NIIcertyyyyMM-ddHHmmss.p12という名前のはずです。
  5. User certificateとして取得したクライアント証明書を選択すると、自動的に選択されるはずです。
  6. クライアント証明書を取得する際に入力したパスワードです。 京都大学 クライアント証明書発行申請システム から確認できます。

emceeで関数フィッティングをする

この記事は CAMPHOR- Advent Calendar の17日目の記事です。

 

初めまして。今年からCAMPHOR-の運営メンバーをやっております、&esです。あんですとお読みください。

 

さて、本日はPythonのライブラリ、emceeを使った関数フィッティングを紹介したいと思います。

 

皆さん人生一度は、任意のデータに任意の関数をフィッティングしたいと思ったことがあるんじゃないでしょうか。そんな時に役立つのが、emceeです。

emcee以外にも関数フィッティングをやってくれるツールは色々あると思います。Excelでも簡単な関数はフィッティングしてくれますし、PythonだったらSciPyとかもやってくれますね。ただ、emceeはパラメータが多くなっても極値で止まってしまうことなく、ちゃんと更新していってくれるため、より良いフィッティングができる(はず)という利点があります。その代わりに計算コストが高いので時間がかかってしまいますが、普通に便利なので使ってみても良いと思います。

emceeとは

emceeはPythonマルコフ連鎖モンテカルロ法(以下MCMC)を扱うためのライブラリです。MCMCというのは、本来

求める確率分布を均衡分布として持つマルコフ連鎖を作成することによって確率分布のサンプリングを行う種々のアルゴリズムの総称

引用元:マルコフ連鎖モンテカルロ法 - Wikipedia

だそうですが、関数フィッティングもできてしまうんですね。しかもフィッティングの誤差まで求まってしまいます。どうしてできてしまうのかはこの記事では詳しく解説しません。私もよく知りません。むしろ教えてください。

emceeの公式ドキュメントにもFitting a model to dataというのがあるのでそれを見てもらえたら良いんですけど、この記事ではもっと簡単に動けばいいの精神で使ってみたいと思います。

emceeを使う

とりあえずemceeとNumPyをpypiなりcondaなりでインストールしておいてください。

適当なデータを用意する

まずはいい感じのデータを用意しましょう。モデルがいい感じの関数で、いい感じにばらついていて、いい感じに誤差が乗っていると良いですね。今回はNumPyを使って適当な感じで作ってみます。random.seedを同じにすれば皆さんも同じデータを作ることができます。

import numpy as np

np.random.seed(0)

N = 40
x = np.linspace(-3, 3, N)
y = 0.5 * x ** 3 + 2 * x ** 2 + 3 * np.sin(3 * x) + 0.5 * np.random.randn(N)

\displaystyle y=\frac{1}{2}x^3 + 2x^2 + 3\sin3x\ \ \ (-3\leq x\leq3)

の関数に正規分布の乱数を載せたものですね。ちなみにこんな感じです。

f:id:and_es:20211216232211p:plain

必要な関数などを定義する

以下の関数をフィッティングすることにしましょう。

ax^3+bx^2+c\sin dx

a, b, c, dがフィッティングパラメータですね。

まず対数尤度関数を定義します。MCMCによるフィッティングは基本的に対数尤度を最大化することで行います。

尤度ってなんぞ、という方のためにほんの少しだけ解説すると、簡単に言えば、ある関数(フィッティングする関数)からそのデータが生成される確率のことです。データがその関数の周りで、正規分布に従って生成されるとすれば、

\displaystyle \prod_i\frac{1}{\sqrt{2\pi\sigma^2}}\exp{\left(-\frac{(x_i-f(x_i))^2}{2\sigma^2}\right)}

となりますね。ただ、積の計算はコストが高いので、対数をとってあげます。

\displaystyle \sum_i\left(\ln\frac{1}{\sqrt{2\pi\sigma^2}} -\frac{(x_i-f(x_i))^2}{2\sigma^2}\right)

そうするといい感じに和の形になってくれます。さらに第1項はフィッティングする関数と無関係なので無視してあげれば、

\displaystyle -\frac{1}{2}\sum_i\left(\frac{x_i-f(x_i)}{\sigma}\right)^2

を最大化すれば良いということになりますね。

したがって、対数尤度関数は、

def lnlike(theta, x, y):
    sigma = 0.5
    a, b, c, d = theta
    model = a *x ** 3 + b * x ** 2 + c * np.sin(d * x)
    chi2 = - np.sum(((y - model) / sigma) ** 2) / 2
    return chi2

こんな感じに定義できます。

あとはこんな感じに必要なものを定義しておきます。

import emcee

init = np.array([2, 2, 2, 2])
pos = init + 0.5 * np.random.randn(32, 4)
nwalkers, ndim = pos.shape
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnlike, args=(x, y))

initはパラメータの初期値です。理論値とかを入れると良いですが、今回は特に物理的なモデルでも何でもないので、適当にすべて2にしておきます。

posでどの値からパラメータを更新するか、と、パラメータの初期化と更新を何回繰り返すか、を定義しています。np.random.radn()の1つ目の値が初期化と更新を何回繰り返すかで、2つ目の値にはパラメータの個数を入れてください。今回は、initを中心に正規分布で値をばらけさせています。違う値からパラメータを更新させることで、より大局的に尤度が最大となるパラメータを探すことができます。

nwalkersとndimはそれぞれパラメータの初期化と更新を繰り返す回数と、パラメータの個数ですね。posのshapeなので当たり前ですが。

samplerでemceeのサンプラーを定義します。3つ目に対数尤度関数を、4つ目に対数尤度関数に渡すデータを与えています。

MCMCでフィッティングする

あとはMCMCを走らせるだけです。

sampler.run_mcmc(pos, 10000, progress=True)

こんな感じですね。2つ目の引数はパラメータの更新を行う回数です。今回は10000回更新してみます。あまり少なすぎるとemceeに怒られますが、あまり多すぎても時間がかかってしょうがないのでいい感じに変えてみてください。

progress=Trueとすることで進捗を表示することができます。tqdmがないと怒られたような気がしますね。

フィッティングパラメータの値を取り出す

flat_samples = sampler.get_chain(discard=100, thin=15, flat=True)
theta = [np.percentile(flat_samples[:, i], [16, 50, 84])[0] for i in range(flat_samples.shape[1])]

こんな感じで値を取り出せます。

ちなみにこんな感じになりました。

print(theta)
[0.47993708089393267, 2.0188253746545453, 2.77740977885968, 2.960187497302918]

まあいいんじゃないでしょうか。グラフにするとこんな感じです。

f:id:and_es:20211217015904p:plain

割ときれいに合ってますね。

あとがき

パラメータに制限をかけていなかったり、プログラムがあまりにも適当だったり、正直言ってこの記事はガバガバです。ただ、emceeを使って複雑な関数のフィッティングができるんだということを知っていただければ幸いです。ぜひ公式ドキュメントなどを読んで試してみてください。それではまたっ。