物理の研究の備忘録

高エネルギー物理学とかいうマニアックな研究分野の博士課程にいるわたしの備忘録。主にPCの設定とかプログラミングとか雑多な感じで

Linux環境でPython、機械学習を使って手書き文字を識別する

 

基本的には以下のサイトの通りに(言われるがままに)やっみた。

【機械学習】Python3 + scikit-learn で識別率99%の手書き数字の分類器を作った - 株式会社クイックのWebサービス開発blog

 

自分の環境はUbuntu 16.04 LTS

環境構築

1.apt-get使ってぱーっと入れる。

sudo apt-get install python3 python-dev python3-pip
sudo apt-get install virtualenv

sudo apt-get install python-pip

2.
mkdir image_classify
cd image_classify
virtualenv -p python3 env
source env/bin/activate

3.

教師データは↓のものを使うよ

MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

# sudoで実行しない
pip install numpy
pip install scipy

# 先にライブラリを入れておく
sudo apt-get install gfortran liblapack-dev
pip install scikit-learn
4.
# データを入れておく場所
mkdir data
cd data
wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
5.
gzip -dc train-images-idx3-ubyte.gz | od -An -v -tu1 -j16 -w784 | sed 's/^ *//' | tr -s ' ' > train-images.txt
gzip -dc train-labels-idx1-ubyte.gz | od -An -v -tu1 -j8 -w1 | tr -d ' ' > train-labels.txt
gzip -dc train-images-idx3-ubyte.gz | od -An -v -tu1 -j16 -w784 | sed 's/^ *//' | tr -s ' ' > test-images.txt
gzip -dc train-labels-idx1-ubyte.gz | od -An -v -tu1 -j8 -w1 | tr -d ' ' > test-labels.txt

6.
適当にimage.pyみたいなの作って以下のコードをかく

#!/usr/bin/env python

import numpy as np
from sklearn.ensemble import RandomForestClassifier

# learninig data
data_training = np.loadtxt('data/train-images.txt', delimiter=' ')
label_training = np.loadtxt('data/train-labels.txt')

# test data
data_test = np.loadtxt('data/test-images.txt', delimiter=' ')
label_test = np.loadtxt('data/test-labels.txt', delimiter=' ')

# learn
#estimator = LinearSVC(C=1.0)
estimator = RandomForestClassifier()
estimator.fit(data_training, label_training)

# test
print(estimator.score(data_test, label_test))

7.

ターミナルで

python image.py

とかやると

0.9990166666666667

と出てきた。とりあえずやってみた感が強いので、明日あたりにちゃんと理解して編集、更新します。

 

 

 

 

物理屋さんのiPhoneアプリ開発日記1~X codeを使ってみる~

はじめに

 

クソゲーを作りたい。

 

 

これは俺の長年の悲願である。

もともと単純作業だったりすごくくだらないクソゲーが好きなので自分でもiPhoneアプリを作ってみたいと思い、Swiftの勉強を始めることにした。

もはやブログのタイトルとまったく関係なくなってきているが気にしない。

 

前回の記事

c++使いのSwift備忘録 - 物理の研究の備忘録

Swiftの超基本的な文法について学んだので、今回はX codeを使ってiPhoneアプリを

作るのに必要なiOS独自のクラスに触れてみたいと思う。

実際の開発に比べるとまだまだ初歩の初歩という感じだが、物理の研究の合間にiPhoneアプリの

開発の勉強をするのはとても楽しいし、いい息抜きになるのでよしとする。

 

準備

 

MacX codeを起動してCreate a new Xcode projectをクリックする。

f:id:hakase73:20180419052356p:plain

今回はiPhoneで動くiOSアプリを作るのが目的なので、iOSにチェックを入れて、Single View Appを選んでNextをクリック。

f:id:hakase73:20180419052544p:plain

プロジェクト情報を入力していく。正直なんでもいいのだけど、Project name

MyAppとかにしてそれ以外を自分の名前とかにした。下の3つのチェックは外しておく。デバイスiPhoneにして、言語はもちろんSwiftにする。(Objective-Cも選べる)

f:id:hakase73:20180419052731p:plain

 

保存場所はどこでもいいけど、とりあえずデスクトップにしておく。

作業画面になった。左側にAppDelegate.swiftとかViewController.swiftとかMain.storyboardとかいろいろ出てくるが、とりあえずMain.storyboardをクリックするとiPhoneの画面っぽい枠がでてくる。なんかそれっぽいぞ!

このストーリーボードってとこで、画面のどこに何を配置してどんな動きをして...みたいなのを作ってくっぽい。

右下のところがらいろいろ部品が選べるので、とりあえずLabelってやつを選んでストーリーボードにぴーっとドラッグしてみる。画面にLabelが貼り付けられた。

↓こんなん。

f:id:hakase73:20180419053820p:plain

 

 右上にある丸が二つ重なってるみたいなやる(Assistant Editor)をクリックすると、に画面編成になって右側にViewController.swiftがでてくる。このViewController.swiftってとこに書いてあるプログラミングが、画面に何をどう表示するかをコントロールしてるっぽい。貼り付けたラベルをコントロールするために、Ctrlを押しながらラベルをドラッグしてViewController.swiftのclass ViewController: ...とか書いてあるとこの下にドラッグする。名前は適当にlabelとかにする。すると@IBOutlet weak var weak label: UILabel!という1行が加わった。

f:id:hakase73:20180419054611p:plain

 これでlabelというクラス変数(インスタンス)を通してストーリーボード上のラベルを制御できるようになった。

 

ラベルの文字を変える。

label.text = "わーい"

の行をviewDiaLoal()関数の中に加える。

その状態で左上の再生ボタン的な奴をクリックする。

シミュレーションの画面に「わーい」と出てくればおっけー。

class ViewControllerってなんや

そもそもここに書かれているプログラミングはなんなのか。

クラスについて知っている前提で話をする。(クラスについては別記事にするかも)

class ViewController: UIViewController{

}

と書いてあるのは、これはViewControllerというクラスについての説明で、UIVewControllerというクラスを継承しているということだ。

このクラスにはVewDidLoad()という関数とdidReceiveMemoryWarning()という二つの関数(メソッド)を持っている。didReceiveMemoryWarning()というのはメモリがやばくなった時に読み込まれるメソッドなので今は気にしない。VewDidLoad()は画面(ビュー)の準備ができたときに読み込まれるメソットで、とりあえずここに変更したいことを加えれば良いことになる。overrideと書いてあるのは継承元のクラスであるUIViewControllerに同じ名前のメソッドがあるけどこっち優先的に読み込んでね!という意味である。ただ、実際にはUIViewControllerクラス内のVewDidLoad()を先に読んで欲しいので、最初にsuper.VewDidLoad()と書いてある。こう書くことで、先に継承元のUIViewControllerのメソッドを読んで、それから変更部分を加えたViewController()クラスのメソッドを読んでくれるということだ。

 

@IBOutletってなんや

次にドラッグした時にできた@IBOutlet weak var weak label: UILabel!について。

@IBOutletっていうのはストーリーボード上からラベルの情報に参照するのに必要らしいけど、うまく説明できないし正確に理解できているかもわからないので今はなんとなくで理解しておく。

var a:Int = 0

とか打つとInt型の変数aが定義されるのと同じように、UILabel型のインスタンスlabelが定義されて、このlabelというインスタンスを通してラベルの情報にアクセスできる。

なのでlabel.text="..."と書くことで、ラベルのテキスト情報にアクセスしてラベルの文字を変更することができる。UILabel!の"!"は非オプショナル型といってnil(つまりデータのない空の状態)を入れちゃいけません、という意味。逆に"?"をつけるとオプショナル型となりnilを入れることが可能となる。weakと書いてあるのはクラスの参照とかメモリがどう解放されるかとかそのへんに関わってくるっぽいけど、とりあえずは気にしない。

 

正直細かいプログラムの定義は使いながらなんとなくニュアンス掴んでいく部分もあると思うし、現時点ではこれくらいの理解でいいかな。

まだラベルの文章変えただけだし、次はもう少しアプリっぽい何かに挑戦したい。

 

おわり。

 

 

c++使いのSwift備忘録

今日から趣味でSwiftの勉強を始めたので普段俺が使ってるc++との違いなどを備忘録的にまとめてみる。

Swiftとは2014年にAppleによって発表された割と新しいプログラミング言語のことだ。Mac関連やiOSアプリを開発しようと思ったらSwiftとお友達になるのが1番の近道だと思われる。Swiftが出てくる前まではObjective-Cという言語がiOSの開発で使われていた。

実は何年か前に一度Objective-Cを勉強しようと思ったことがあったんだけど、いろいろと癖が強すぎて早々に挫折。最近になってSwiftについて少し調べてみたらObjective-Cに比べて随分とっつきやすい気がしたので再度挑戦してみる。

現在の開発環境はMac OS Sierra 10.12.5, X code8.3.2

ターミナルでswiftとコマンドを打ち込んでインタープリタとして使うこともできるけど、せっかくなのでX code開いて作業することにする。

 

四則演算とか

コメントアウト//または/* */なのでc++と同じ。四則演算も+-*/%等まったく同じ

に使えるので楽。この時点で妙に親近感を覚えるね。まぁこのへんはどの言語でも

似たようなものなのかもしれないけど。

 

実行結果の出力とか

print(“hoge”)

みたいな感じで出力できる。c言語でいうprintfc++でいうところのcout

Pythonprintだからpythonと同じって考えていいのかな?

ちなみに文字列は

print(“aaa+bbb”)

みたいな感じで足し算で簡単に繋げられるので便利。c++stringっぽい感じで使えるぞ。

てかSwiftって文末に;いらないのね。なんかpythonみたい。

型はおなじみのInt, Float, Double, Bool, Stringなどが普通に使える。

キャストも(Double)3みたいな感じだからc++とほぼ同じ。これはSwiftに限った話じゃないけど、Intと打った場合にどれくらいの容量が確保されるかはマシンスペックに依存する。なので、厳密に管理した場合はInt64みたいな感じで明示的にbit数指定することもできる。

 

変数や定数の宣言

c++だと

int a= 1;

と書いていた部分、Swiftだと

var a : Int =1

てな感じになる。:Intの部分で型を指定してるけど

var a = 1

みたいな感じで省略すると勝手に型推論してくれる。ただし型推論ばっかりしてるとコンパイルに時間かかっちゃうみたいなので、できるだけ明示的に型指定したほうがいいのかな?

定数の場合はvarの代わりにletを使う。なので

let b : Float = 10.0

c++でいう

const float b=10.0

と同じ。ちなみにc++だと10.0と書く代わりに10.と打ってもよかったけど、Swiftだとエラー出た。ちゃんと0まで書かないといけないのね。

 

配列

 c++だと、可変長の時はvectorを使って、普遍なときは普通の配列を使うって感じで雑多で統一感がない感じだったけど、Swiftの場合可変、不変はvarとletを使い分ければよくて、わりとすっきりしている。

・不変の場合

c++だと

const int array[3]={1,2,3};

Swiftだと

let array : [Int] =  [1,2,3]

・可変の場合

var array : [Int] = [Int]()

array.append(1)

array.append(2)

...

みたいな感じで要素追加する。

print(array[0])

とやるとちゃんと1が出力された。なんか[Int]()って書き方慣れないな。初期化的なことをしてるのかな?

 

関数

Int型の引数を2倍にして返す関数を考えてみる。c++だと 

int test(int a){

   int b = 2*a ;

   return b;

}

//in main function

cout<<test(5)<<endl;

出力結果:10

Swiftだと

func test(a : Int)->Int{

    var b = 2*a; //or var b:Int =2*a

    return b

}

//in main fuction

print(test(a:5))

出力結果:10

 

こんな感じ。慣れるまで時間かかりそうだな。2変数だと

func test(a : Int,b : Int)->Int{...}みたいな感じで適当に書いてみたら回った。

for文

1から10までの和をfor文で回すとする。足すたびに出力もする。

c++だと

int sum=0;

for(int i=0;i<10;i++){

  sum+=i+1;

  cout<<"sum="<<sum<<endl;

Swiftだと

var sum=0

for i in 0...9 {

    sum+=i+1

    print("sum=\(sum)")

}

出力結果

sum=1

sum=3

sum=6

sum=10

sum=15

sum=21

sum=28

sum=36

sum=45

sum=55

繰り返し回数が0...9で10回足されてることに注意。

\(sum)って書いてあるのはInt型の変数を文字列にぶち込みたい時にこう書けるらしい。

print("sum="+String(sum))

としても同じ。

cと同じ文法でfor文が回せる...?

少し調べてみると、このfor文の使い方はRubyに近いらしく、c言語ユーザーに馴染み深い記法

for(var i=0;i<10;i++)...

でも回ると書いてあった。俺的にはこっちの方が慣れ親しんでるので「やったー」と思いながら打ち込んでみたら

error: C-style for statement has been removed in Swift 3

なるエラーが出た。えぇ。。この書き方はSwift3で廃止になったみたいだ。ひどいよ...

まだ比較的新しい言語だから色々変わってる最中なのかな。ちなみに++,--もSwift3から廃止らしく、「i++じゃなくてi+=1のような書き方をしてね!」ということのようだ。

if文

cとほぼ同じ。cだと

if(a<10){

 ...

}

と書くとしたら、Swiftだと

if a<10{

 ...

}

と書けばいい。()がなくなっただけだね。elseも同様。これはすぐ覚えられそう。

 

X codeでプログラムを打ってみる

x codeにはPlaygroundってやつがあって、プログラムを打つとその場で出力結果を教えてくれるモードがある。今までのプログラムを打つとこんな感じ。

f:id:hakase73:20180419050257p:plain

今回は別にSwiftの文法に限った話で、特別iOS開発に関する事柄はでてこなかったので、次はiOS独自のクラスを使いながらiOS開発、オブエジェクト志向について学んでいこう。

おわり

負の二項分布(Negative Binomial Distribution)について学ぶ ~数式編~

負の二項分布とは

負の二項分布を使う機会があったのだけど、定義がいっぱいあってよくわからないので調べたことをまとめてみる。

日本語版wikipediaだと一つの定義しかないが、英語版wikipediaの項目(Negative binomial distribution)が割と充実していたので英語版wikipediaを見ながら学ぶ。

NBDと呼ばれることもあるね。

 

二項分布については使われる機会も多く、少し調べてみると充実した解説が山ほど出てくるが、負の二項分布についてはあまり充実した情報はないようだ。英語版wikiによると全部で5つの定義があるみたい。式書くのめんどくさいので以下スクショ。

f:id:hakase73:20180217185557p:plain

↓リンク

Negative binomial distribution - Wikipedia

 

ここでは試行回数:n、成功した回数:k、失敗した回数:r、成功する確率:pと定義する。

当たり前だが k+r=n の関係が成り立つ。

5つはそれぞれ

1:r回失敗する前に何回成功したか

2:r回失敗するのに必要な試行回数

3:k回成功する前に失敗した数

4;k回成功するのに必要な試行回数

5:n回の試行で何回成功したか(二項分布)

となっている。

 

一番わかりやすいのは5番目の定義で、これは二項分布の定義そのもの。

n回の試行に対して何回成功したかという確率分布である。

コインを100回投げたとき何回表が出たか、みたいなやつね。

成功した回数の分布を見ているのでf(k;,n,p)とkの関数になっていることがわかる。

4つ目の定義については確か日本語版wikipediaで説明されていた気がする。

このように、二項分布の場合は定義が一つだが、負の二項分布の場合はそれぞれ定義が微妙に違うあるので、もし「負の二項分布を使って〜」みたいな説明を見たときはどの定義なのかちゃんと注意する必要がある。

これら5つの式は割と簡単に導くことができる。試しに1つ目の定義について考えてみる。

n-1 (k+r-1)回の試行でk回成功して、n回目で失敗すればいいので、

 \begin{align}f(k:r,p) &=\begin{pmatrix}{r+k{-}1}\\{k}\end{pmatrix}p^{k}(1-p)^{r-1}(1-p)\\ &=\begin{pmatrix}{r+k{-}1}\\{k}\end{pmatrix}p^{k}(1-p)^{r}\end{align}

 てな感じ。他も同様に導ける。そんなに難しくないね。

せっかくなのでもう少し踏み込んでみよう。

実数に拡張する

 この定義式だとrもkも整数しかとれない。成功回数が何回か、みたいな議論をしてるので当然だけども。これを正の実数に拡張してみよう。そうすれば連続的な関数として取り扱うことができるようになるはずだ。全部の定義でやるのはかったるいので、1番目の定義に絞ることとする。

まずは階乗の部分をガンマ関数に

ガンマ関数についてはぐぐればいくらでも出てくるので詳しくは書かないけど、これを使えば階乗の概念を連続的な量に拡張できる。

\begin{align}\Gamma{(n+1)=n!}\end{align}

であることを考えれば

\begin{align}\begin{pmatrix}{r+k{-}1}\\{k}\end{pmatrix}&=\frac{(r+k{-}1)!}{k!(r-1)!}\\&=\frac{\Gamma{(r+k)}}{\Gamma{(k+1)}\Gamma{(r)}}\end{align}

となるね。

分布の平均値をパラメータとして使う

さて、これで一通り準備は揃ったような気もするけど、最後に分布の平均値(期待値)を計算してそいつをパラメータにしよう。

なんでそんなことするのかって?

ポアソン分布にしろ、ガウス分布にしろ、平均値を表すパラメータが式の中に入ってるじゃん。なので成功確率pをそのまま使って表すよりも平均値を用いたほうが分布の形状を考えるとき扱いやすいよね。まぁ理由なんてなんでもいいんだけど、とにかく平均値を考える。

と言っても考え方は二項分布のときと同じで、試行回数にpをかければ成功回数になるし、(1-p)をかければ失敗回数になるので以下の式が成り立つはずだ。

\begin{align}\frac{\langle{k}\rangle}{p}=\frac{r}{1-p}=k+r\end{align}

\begin{align}{\langle{k}\rangle}=\frac{pr}{1-p}\equiv{m}\end{align}

 平均値を表すパラメータをmと定義した。

あれ、kには期待値記号が付くのにrに付かないのはなぜ?と思う人もいるかもしれないが、現在の定義だとkについての関数になっていてrは固定値なので期待値記号は付かない。もちろん別の定義のNBDの定義だと変数も変わる。

 

これらを用いれば最終的には

\begin{align}f(k;r,m)&=\frac{\Gamma{(r+k)}}{\Gamma{(k+1)}\Gamma{(r)}}\left(\frac{m}{r+m}\right)^{k}\left(\frac{r}{r+m}\right)^{r}  \end{align} 

あるいは 

\begin{align}f(k;r,m)&=\frac{\Gamma{(r+k)}}{\Gamma{(k+1)}\Gamma{(r)}}\left(\frac{m}{r}\right)^{k}\left(\frac{m}{r}+1\right)^{-(r+k)}  \end{align} 

とかくことができる。

上の方の式は英語版wikipediaにも載っているので参照にされたし。

おわり。 

なぜ加速器を使うのか?〜素粒子と初期宇宙〜①

さて、ここでは加速器素粒子についておおまかな背景を述べる。

僕は原子核衝突実験の人なので、だいぶそっち方面に偏った説明になるかもしれない。

 

加速器の話

スイス、フランスの国境付近に CERN(欧州原子核研究機構)と呼ばれる研究所があり、せるんとか呼ばれている。CERNにはLHCと呼ばれる山手線一周ほどの巨大な円形加速器がある。

LHCは多くの国と研究機関が力を合わせて1兆円もの大金をかけ作られた大規模なものであり、小さな小さな粒子をほぼ光速度まで加速、衝突させては、世界中の物理学者がキャッキャウフフと喜んでいるのだ。

LHCだけでなく世界中に様々な加速器があり、日本にもJ-PARCやKEKと呼ばれる加速器がある。ここではその種類については詳しくは述べないが、僕が言いたいのは世界中の科学者がこぞって加速器をつくっては高いお金をかけて実験しているということだ。

なぜこんなことをするのだろうか?

一般の人にとっては彼らは気が狂っているとしか思えないだろう。またはお金の無駄遣いにしか思えないだろう。

ここではなぜ彼らがそこまで加速器に熱中するのかを言いたいと思う。

 

f:id:hakase73:20170708000954j:plain

CERNの上空写真。加速器は地中に埋まっているので直接は見えないが、とにかくでかい。

 

原子と原子核の話

加速器の話をいったんおこう。

「物質の最小の構成要素はなにか」というのは人類が長い間ずーっと追い求めてきた課題である。誰もが一度は考えたことがあるのではないだろうか?

小学校ですべての物質は原子からできていると習うだろう。

といっても原子も最小の構成要素ではなく、原子はさらに原子核とその周りを回る電子から成る。

原子核はさらに陽子や中性子からできていて、陽子の数で原子の種類が決まる。

例えば水素なら陽子が一個だし、炭素なら12個である。

中性子の数は関係ないのかって?

まったく関係なくはないのだが、原子の性質はほとんど陽子で決まる。

その理由は中性子電荷を持たないが、陽子は+1の電荷を持っていることに起因する。

原子は全体で電荷中性になるのが安定になるため陽子と同じ数だけ電子が外側を回っている。化学反応というのはざっくり言えば電子をやりとりする反応なので、陽子の数=電子の数=原子番号 であり、これが原子の種類を決めることになる。

ここらへんは主に化学の話で、一般の物理を専攻としていない人が学校で習うのはこのへんまでだろう。

f:id:hakase73:20170708001651g:plain

↑原子のイメージ、中国電力HPより

 

素粒子の話

陽子や中性子をまとめて核子と呼ぶが、核子はさらに3つのクォークと呼ばれる素粒子からできており、これが物質の最小の構成要素である。(と現在では考えられている)

この世界に存在するすべての物質は原子からできていることを考えれば、つまるところ物質の最小の構成要素である素粒子の性質がわかればこの世界はどのようにできているのかということを突き止められるかもしれない。

素粒子を研究するということは物質の根源に迫るということなのだ

素粒子の種類は1つではなくいくつか種類があり、標準模型と呼ばれる理論でまとめられている。

f:id:hakase73:20170708002324p:plain

標準模型素粒子は実は1種類じゃなくていろいろある。

 

レプトンと書いてあるのは電子の仲間で3種類あるニュートリノレプトンである。e、μ、τの3種のレプトンはどれも-1の電荷を持つが、ニュートリノ電荷も持たなければ質量もほぼ0 であるためほとんどの物質もスカスカすり抜けてしまう。

ほとんどの人にとっては「電子は知ってるけどμ粒子やτ粒子なんて知らねーよ」

って感じだろう。これはμやτは電子に比べて質量が重く不安定なのですぐに崩壊していまうためである。

クォークと書いてあるのが陽子や中性子のような物質を形づくっている素粒子である。右にあるボソンというのは相互作用を媒介する粒子であり、ヒッグスと書いてあるのは物質に質量を与えるヒッグス粒子という割と最近(ようやく)見つかった粒子である。

また、クォークレプトンにはそれぞれ電荷などの物理量が反転して反粒子というやつがいる。例えば電子の反粒子陽電子というプラスの電荷を持つもので、電子の陽電子が出会うと対消滅してエネルギーに変わる。我々が普段反粒子を見かけないのはこの世界は粒子の数>反粒子の数であり、反粒子が生成されてもすぐに対消滅して消えてしまうからだ。SFとかで好まれそうなネタだ。

反粒子が発見の歴史は…...などなどと全部説明しているときりがないのでこれくらいにしておいて、ここでは核子とそれを構成するクォークに注目してみよう。

クォーク強い相互作用の話

陽子や中性子などの核子は3つのクォークから構成されている。

uクォーク2個とdクォーク1個から構成されているのが陽子で、uクォーク1個とdクォーク2個から構成されてるのが中性子である。

上の表を見るとuやd以外にもbとかtとかいろいろあるが、これら前述のμやτ同様質量が大きくすぐに崩壊してしまうので自然界でではなかなかお目にかかれない。

これらの重い粒子は加速器を用いて人工的に創りだすことで実験で初めて発見されたのである。(ただしμ粒子なんかは実は宇宙線として空から降ってきたりしている)

 

原子核の周りを電子が回っているのは電磁気力によるものだが、クォーク同士や陽子と中性子同士は強い相互作用と呼ばれる力で結びついている。

f:id:hakase73:20170708003254p:plain

3つのクォークグルーオンと呼ばれる素粒子を媒介として結びついている。

媒介として、というのは物理を専門にしていない人にはしっくりこないかもしれない。

例えば電磁気力を例に取ると、プラスの電荷を持った粒子とマイナスの電荷を持った粒子

には引力が働くが、素粒子論だとこれを光子をキャッチボールのようにやり取りすることで引力が働くと考える。光子というのはつまりは光のことである。光は電磁波という波であるが、素粒子の世界ではこれをひとまとまりの粒子のようにとらえ、「光子」と呼んでいるのだ。

同じようにクォークグルーオンと呼ばれる素粒子を通して結びついているのである。

 

さて光子と呼ぶとピンとこなくても、電子や光を知らない人はいないだろう。

しかしクォークグルーオン強い相互作用と言われても日常生活でそれを感じることはまずない。その理由は強い相互作用原子核内部のごくごく近距離でしか働かないからである。

原子核にくらべてずっと大きなスケールで生活いている僕らには日々の生活で強い相互作用を感じることはないのだ。

我々が日常生活で感じる「力」は重力を除き、すべて電磁気相互作用によるものだと考えて良い。

また、強い相互作用は力が働く範囲こそ狭いが、電磁気相互作用に比べてめちゃくちゃ強い。名前の由来もそこにある。

放射線被爆の恐ろしさも実はそのへんに密接に関連している。

我々が普段目にするような化学反応は原子核の周りを回る電子の反応であるが、放射線原子核の崩壊によって飛び出してくる粒子である。

したがって放射線は通常の化学反応と比べて桁違いのエネルギーを持っているため、人体に浴びてしまうとDNAを傷つけてしまうのである。これが俗に言う被爆だ。

放射線を理解するには原子核の性質を理解することが重要なのである。

 

ちなみに、中高校生時代僕は陽子はプラスの電荷を持ってて反発し合うはずなのに原子核が結びついているのはおかしくないか?とずっと思っていたが、これも電気的な反発力よりも強い相互作用のほうが文字通り結びつきが「強い」からである。

どんどん脱線してしまうが、この陽子と中性子は中間子と呼ばれる粒子を媒介として結びついており、この中間子の存在を予言してノーベル賞をもらったのがかの有名な湯川秀樹である。

 

クォークの性質をどうやって調べるか?

原子はとても小さいので顕微鏡で直接みることなんて不可能だった。そのため昔(といっても100年位前の)人はあれやこれやとがんばって原子の存在を立証したのである。*1ただ最近はからり技術が発達してきて、驚くべきことに原子のスケールでは実際に原子を顕微鏡で見たりつまんで動かしたりできるようになったらしい。IBMという企業が原子の配列を変えて世界最小のアニメーションを作ったのが少し前に話題になったが、これは本当にすごいと思う。

f:id:hakase73:20170708005600j:plain

↑原子の配列を変えて作った世界最小のアニメーション

 

ただ、原子に比べて原子核はさらに小さいのでこんなことはまだできない。

原子も原子核もどっちも小さいのでピンと来ないかもしれないが、原子に比べて原子核はめちゃくちゃ小さい。原子の大きさがだいたい{ \displaystyle 10^{-10}}mなのに対して、原子核の大きさは{ \displaystyle 10^{-15}}mくらいなので5ケタ違う。よくある例えだと、原子が東京ドームだとすると原子核の大きさはその中に置かれた一円玉くらいの大きさだ。

さらにやっかいなのはクォークの閉じ込めと呼ばれる性質だ。

電磁気の場合はプラスの粒子とマイナスの粒子を遠ざければ遠ざけるほど力は弱まるが、グルーオンの場合クォークの距離を引き伸ばせば引き伸ばすだけ結合が強くなるバネのような性質がある。

クォーク核子から取り出そうとするには無限のエネルギーが必要となってしまい、もはや小さいうんぬんの話ではなく、クォーク1個を取り出して見ることは原理的に不可能なのだ。

これでは八方塞がりであるが、これらを打開する手が実は一つだけあるのである。

 

つづく。

 

*1 このへんの原子の発見の歴史はめちゃくちゃ面白い。「だれが原子をみたか」という本がおすすめ。原子の発見の歴史がわかると改めて熱力学や統計力学というものが楽しくなるだろうと思う(僕はなった)。今でこそ熱=原子の運動というのが常識となっているが、実は熱力学の理論が確立したのは原子の発見よりも前なのである。熱力学が原子の存在を過程しなくてもマクロな物理量だけを使って体系的に成り立っているのはとても興味深い。このへんは田崎晴明さんの「熱力学」「統計力学」なんかがおすすめ。

高エネルギー物理の基礎〜はじめに〜

はじめに

さて、このブログは今までタイトルの通り自分用の備忘録として使ってきた。

PCとかプログラミングの設定などのメモを中心に書いてきたが、せっかくなので自分が専攻している物理学、特に高エネルギー物理学と呼ばれるものについてもまとめておこうと思う。

高エネルギー物理のカテゴリから順番に、教科書のような雰囲気で読めるようにするのが目標である。

なので、順番を変えたり、記事の内容をあとから修正したりということが割と頻繁に起こるかもしれない。

今までの記事は自分用のメモであったが、このカテゴリの記事は多くの人に読んでもらいたいと思っているし、疑問に思うところや間違いなどがあれば積極的に指摘、議論してもらいたいとも思っている。

 

想定している読者層

高エネルギー物理を専攻している学生だけでなく学部生の物理の学生、素粒子物理学原子核物理学に興味を持ち始めている物理を専攻していない人にも広く読んでもらいたいと思っている(願望)。

ただ、ブリーバックスやニュートンみたいな基本的に数式が出てこない本と違って、数式を出しながら説明していきたいと考えているので、数式に拒否反応を示す人は読むのが辛くなるかもしれない。数式を読み飛ばしながら読んでもわかるように考慮はするつもりである。

これからの記事をよんでなんとなく「あーこの分野の人たちはこういうことをやっているのかぁ」

ということが伝わればいいと思う。また、このブログは高名な物理学者の人が書いた本と違い、ポンコツの一学生が頑張って書いているものなので、記事の内容を鵜呑みにするのは非常に危険である。

なぜこんな記事を書こうと思ったか

さて、なぜこのようなうぬぼれたシリーズの文章を書こうと思ったのかについてもまとめておこう。僕が大学学部生の時に最も衝撃を受けたサイトが「EMANの物理学」というサイトで、物理を専攻している人なら一度は聞いたことがあるのではないかと思う。

当時大学で使っていた教科書からはどうも堅苦しさを感じていたのだけど、webサイト上でこんなにもわかりやすく、面白く物理を語ることができるのかと当時の僕は夢中になり、サイト内の文章はすべて読破した。今の自分が物理を好きだと言えるのはかなりこのサイトの影響があると思う。それと同時に自分が勉強した物理について文章を書いてもこのサイトの二番煎じや下位互換にしかならないと思い、自分から積極的にこのような文章を書こうとは思いもしなかった。

きっかけは修士論文

さて、満を持して修士課程に進んだ僕であったが、そこでは高エネルギー物理の分野で初めて触れるような式や用語がたくさんあった。そして、それらに関連する文章を読んで「わかり辛いなぁ」と思うことが多々あった。

先に言い訳をしておくと、別にその分野の本や論文を書いている人の説明する力がないわけでなく、専門家の脳内ではちゃんと理路整然と理解できているのだと思うが、頭の弱い僕にはそれがどうにもわかりづらい文章に感じてしまったのである。

自分のような馬鹿や、普段論文を頻繁に読んでいない層にもわかるような文章を書けならいいな、と思う。そしてそれをきっかけとして少しでも物理に興味を持ってもらえれば、とも思う。

修士論文を書くときに指導教官の一人から「修士論文は未来の後輩に向けた教科書を書くような感覚で書くといいよ」というようなことを言われて張り切ったのだけど、仮にも「論文」と名前のつく性質上あまりいい加減は文章はかけず、どうにももやもやした気持ちが残った。

このブログはそんな自分の憂さ晴らしである。

偉そうなことをいっぱい書いたが、まだまだ模索している段階なので暖かく見守ってもらえればと思う。

 

 

 

丸め誤差の恐怖〜浮動小数点数の扱いに注意する〜

丸め誤差は予想以上に厄介であることを思い知らされた。

こいつのせいで予想外のバグとの格闘に時間を割かれてしまったのだ。

自分への戒めとしてこの文章を残す。

 

丸め誤差とは?

簡単な例として10/3を考えよう。10を3で割り切ると

3.33333....

と永遠に続き割り切れない。これらの情報すべてを正確に残すには無限の容量が必要なので適当なところで打ち切る必要がある。有効数字10ケタまでを情報として残そう!みたいな。

こうやって有効数字の桁数で切り捨てた時に発生する誤差が丸め誤差である。

ただ、これは10進数の場合であり、コンピュータは2進数なのでちょっと異なる。

例えば0.1は10進数だと誤差なしで書けるけど、2進数で表現すると0.000110011...みたいな循環少数になってしまう。

僕達はふだんついつい10進数脳で物事を考えてしまう上に、丸め誤差もあまり気にせずプログラムを書きがちだけど、これは要注意である。

 

自分がハマった例を書く。

x、yと2つの量(3つの要素をもつベクトル)があったとして

x=(3,3,4)

y=(1,2,7)

とする。ここでx-yの期待値を考えてみよう。xもyも3つの要素をすべて足すと10になるのでx-yの期待値は0になるはずである。実際に手計算してみると

{(3-1)+(3-2)+(4-7)}/3 = 0

まぁ当たり前の結果だ。

次にこれをc言語で書いてみる。

double a = 3/3. + 3/3. + 4/3.;

double b = 1/3. + 2/3. + 7/3.;

cout<<a-b<<endl;

んで出力は0になるかというと思えば

-4.440892e-16

とか出てくるのである。0じゃない。

3で割った時に丸め誤差がab間で発生してしまい、差をとっても0にならなくなってしまうのだ。

 

「10の-16乗でしょ?ほとんど0なんだから問題ないじゃん」

とか思うかもしれないがそうでもない。

例えばa-bの逆数をとって

c=1/(a-b)

を計算したいとする。

(a-b)が0だとこの量は発散してしまうので、

if((a-b)!=0) c = 1./(a-b);

とか書けばa-bが0じゃないときだけ計算してくれることになるが、先ほどの値を使うと0じゃないので

普通にこのif文をtrueとみなしてしまい、結果とんでもない値がcに代入されてしまう。

 

解決策

足してから割ればうまくいった。

 

double a = (3 + 3 + 4)/3.;

double b = (1 + 2 + 7)/3.;

cout<<a-b<<endl;

一度足してしまえば割り算は一回なので、誤差が発生するリスクも少ない。

今回の場合はどちらも10/3.を計算することになるのでぴったり一致する。

 

誤差の桁の意味

せっかくなのでもう少し踏み込んでみよう。

最初の例だと

a-b=-4.440892e-16

なので、15桁は一致していて、16桁目がずれていることになる。

今回は浮動小数点数のdoubleを使っているが、doubleの場合

(符号1ビット)*(仮数部52ビット)*(指数部11ビット)

の62bit = 8byteからなる。

今回の例だと指数部は問題ないので、大事なのは仮数部の部分で、ここが有効数字の桁数を決めてると考えて良い。

2^52=4.5035996e+15

なので、仮数部は10進数で15桁くらいの精度で計算できることになる。

そう考えると16桁のオーダーで誤差が発生するのもうなずける気がする。

 

んーと、合ってるかな??

 

*余談

丸め誤差と似たような量として打ち切り誤差ってのもある。

これサイトによって書いてあることが違って、あるサイ卜だと

「無限級数などの無限に続く計算を途中で打ち切った時に生じる誤差」

っとか書いてある一方で

「循環少数などの計算を途中で打ち切った時に生じる誤差」

って書いてあるページもある。

前者だと足し算の項とかを足すのを途中でやめてるわけだから今回の例とはちょっと異なるし、後者だと今回の無限小数の例も打ち切り誤差ってことになる。

どっちなんだ。手元の本だと前者に近くて、丸め誤差と打ち切り誤差は区別されている。

まぁ無限に続いているものを途中で打ち切ることで生じる誤差、という意味では丸め誤差と似たような量なんだろう。

他にも情報落ちケタ落ちオーバーフローとかいろいろあるけど、今回はこのへんで。

 

まとめ

・割ってから足すな、足してから割れ

 

おわりー