こんにちは!本日のアドベントカレンダー担当は、うまうまです。
滑り込み? そんなことはありません。ハワイ時間なら全然OKです。
さて突然ですが、星座占いは好きですか? 私はあまり信じていませんが、読むと現実のこととなりそうなので目を背けています。むしろ信じている人間の行動かもしれません。
星座といえば天文学の世界では「88星座」というものが決められています。日本天文学会が作成している天文学辞典によると、星座とは以下のような起源があるようです。
天球上の星の並びを人、動物、物などに見立てて呼び名をつけたもの。古代メソポタミア文明が起源とされるが、さまざまな文明がさまざまな時代にそれぞれの星座を作り上げた。北天の多くの星座のルーツは古代ギリシャ文明にあるが、南天の星座は、16世紀の大航海時代以降に作られたものに由来する。
https://astro-dic.jp/constellation/
身の回りの物をモチーフにしたり、神話をモチーフにしたり、果ては実在する人物を称えたりと、かつては色々な地域でそれぞれ設定されていた星座ですが、実は今日使われている星座は1928年に国際天文学連合の総会で決められたもの。使われなくなった古い星座もなかなかユニークなので、一度wikipediaなどでご覧いただくと楽しいかもしれません。ちなみに筆者は「マエナルスさん座」という山の星座がお気に入りです。今はもう使われておらず、うしかい座の一部となっています。この星座、モチーフが山のくせに、うしかい座の足とのスケールがおかしいところがツボです。
で、なにがテーマなの?
あまりにも雑談がすぎました。さて、本記事のメインは「星座の決め方」です。今の星座は昔の人々が、「あの星とあの星、線で結ぶと●●に見えるから●●座」と好き勝手に決めまくった結果の名残なわけですが、もう少しスマートに決めたいと思いませんか?
さて、令和の時代のスマートといえばなんでしょうか? このところ流行りの「DX」「AI」「機械学習」で間違いありませんね! と、いうことで、本記事のテーマは人工知能に88星座を作らせてみた! になります。
いきなり人工知能に星座を作らせると言っても、似非科学感が満載です。まずは人工知能の定義から始めましょう。
人工知能というのは、簡単にいえば「アルゴリズムで人間の思考を真似させる」モノです。言葉としてはかなり曖昧かつ幅広いもので、これといった定義が無いのが現状です。たとえば、深層学習と呼ばれる手法は工知能の枠組みの一つですし、定義によっては「if文」すら人工知能と言えるでしょう。今回はその人工知能の中でも「機械学習」とよばれる部類、さらに詳しく見ると「教師なし学習」と呼ばれるものを用いてみようと思います。
ごちゃごちゃ書きましたが、要はここで言う人工知能というのは、データの塊を入れたら何かの数値を予測したり分類したりしてくれるモノだと思っていただければ大丈夫です。
88星座を生み出そう
今回は、教師なし学習の中でも「K-means」と呼ばれるアルゴリズムを使ってみたいと思います。そもそもどうやって星座を作らせるのか、という点ですが、ここは思い切って「天球面上にある5等よりも明るい星を88個のグループに分ける」というお題にすり替えようと思います。K-meansというのは、非常に簡潔に述べれば、「あるベクトル空間内に分布する多数のデータ点をよしなにグループ分けする」アルゴリズムです。タスクとしては「教師なしクラスタリング」と呼ばれるもので、正解のクラスタがない状態のデータをいい感じに分類してくれます。クラスタリングに関してはK-meansの他にも沢山のアルゴリズムが存在しています。今回は「やってみた系」ということもありますので、とりあえずアルゴリズムの選択には時間をかけず、このK-meansを用います。
さて、ここからはアドベントカレンダーらしく(??)コードを見ていきましょう。コードの汚い点、怪しい点はご容赦ください……。
# 必要なモジュールのimport
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
# 星のデータの読み込み
df= pd.read_csv('star_map.txt', sep='\t', header=None,
names=["HIP","RA","DEC","mag","name"]) \
.query('mag < 5')\ # 5等級よりも明るいものに制限
.fillna("no_name")
# 等級に応じてマーカーサイズを変える
def func_cate(x):
if x < 1:
return 6
elif x >= 1 and x < 2:
return 4
elif x >= 2 and x < 3:
return 3
elif x >= 3 and x < 4:
return 2
else:
return 1
df["size"] = df["mag"].apply(func_cate)
# K-meansに突っ込む用に整形
X = df[["RA","DEC"]].to_numpy()
# K-means実行
kmeans = KMeans(n_clusters=88, random_state=3).fit(X)
df["group"] = kmeans.labels_
# クラスタリング結果をplotしてみる
for i in df['group'].unique():
tmp = df.loc[df['group'] == i]
sns.scatterplot(data=tmp, x="RA", y="DEC", size="size", legend=None)
(データは「Astro Commons」様のページから借用しています。ありがとうございます。)
図の中の点の色はグループ分けを表し、点のサイズは星の明るさを表しています。当たり前ですが、近いところの星が同じグループに分けられています。コードの中のKMeans(n_clusters=88, random_state=3)
のrandom_stateを変えることでグループ分けも変わってくるので、ぜひランダムシードを変更して自分だけの真・88星座を作ってみてはいかがでしょうか?
おわりに
今回は分類しただけで終わってしまいましたが、本来であれば天球面へのプロット、現88星座との比較、アルゴリズムによる差、オレオレ星座絵なんかも手を出したかっところです。来年のアドベントカレンダーに乞うご期待、というところですね!
ところでこの記事のネタ、弊サークルのおさむさんの記事を読んで思いつきました。ということでおさむさんには感謝を…!
では最後に皆さんにクリスマスプレゼントということで、4℃の黒体放射スペクトルのプロットを贈ります! クリスマスといえば4℃ですね! それでは!!
執筆者紹介
執筆:うまうま ( https://twitter.com/hanaco117 )
この記事は Astro Advent Calendarの企画記事です
コメント