アイヌ語の「方言」をnetworkxのspectral_layoutで3D可視化する

小野洋平・深澤美香『[比較不可能だったアイヌ語方言分類 ―統計的方言分類を類似判断の点から再考する―](https://doi.org/10.14943/Jais.4.093)』(アイヌ・先住民研究, 第4号 (2024年3月), pp.93-126)が面白かったので、表6の方言語彙類似度を、networkxのspectral_layoutで3D可視化してみることにした。端的には、表6の値からSzymkiewicz-Simpson係数(もどき)を計算して、それを完全グラフの各枝のweightにしている。Google Colaboratoryだと、こんな感じ。

```
!pip install networkx plotly
import networkx,numpy
from plotly.express import scatter_3d
h=["八雲","長万部","幌別","平取","貫気別","新冠","様似","帯広","釧路","美幌","旭川","名寄","宗谷","落帆","多蘭泊","真岡","白浦","ライチシカ","内路","千島北部","千歳"]
w=[[110,107,104, 99,100, 99,102,100,102, 99,104,101, 97, 74, 77, 77, 78, 79, 77, 73, 99],
   [107,110,102, 97,100, 98, 99, 97, 99, 96,101, 99, 95, 74, 74, 75, 75, 76, 74, 70, 98],
   [104,102,110,105,103,104,101,102,103,101,105,103, 96, 77, 82, 82, 81, 83, 82, 76,101],
   [ 99, 97,105,110,108,107, 95, 96, 97, 95, 99, 99, 92, 78, 81, 81, 80, 82, 82, 78,105],
   [100,100,103,108,110,106, 95, 95, 96, 93, 98, 99, 94, 79, 79, 80, 80, 80, 79, 76,105],
   [ 99, 98,104,107,106,110, 96, 97, 98, 96,100, 97, 90, 75, 79, 79, 78, 80, 79, 77,105],
   [102, 99,101, 95, 95, 96,110,105,106,101,102, 99, 96, 72, 74, 74, 75, 76, 74, 73, 96],
   [100, 97,102, 96, 95, 97,105,110,110,106,102,102, 95, 71, 75, 75, 75, 76, 75, 74, 95],
   [102, 99,103, 97, 96, 98,106,110,110,106,103,104, 98, 71, 75, 75, 75, 78, 75, 75, 97],
   [ 99, 96,101, 95, 93, 96,101,106,106,110,102,101, 95, 70, 75, 75, 74, 78, 74, 73, 93],
   [104,101,105, 99, 98,100,102,102,103,102,110,105, 96, 76, 79, 79, 79, 82, 79, 75,100],
   [101, 99,103, 99, 99, 97, 99,102,104,101,105,110,101, 79, 82, 83, 81, 84, 82, 74, 97],
   [ 97, 95, 96, 92, 94, 90, 96, 95, 98, 95, 96,101,110, 83, 85, 88, 85, 86, 82, 71, 92],
   [ 74, 74, 77, 78, 79, 75, 72, 71, 71, 70, 76, 79, 83,110, 97,101,101, 99, 99, 63, 77],
   [ 77, 74, 82, 81, 79, 79, 74, 75, 75, 75, 79, 82, 85, 97,110,106,100,101, 99, 67, 79],
   [ 77, 75, 82, 81, 80, 79, 74, 75, 75, 75, 79, 83, 88,101,106,110,105,103,103, 67, 80],
   [ 78, 75, 81, 80, 80, 78, 75, 75, 75, 74, 79, 81, 85,101,100,105,110,104,102, 67, 80],
   [ 79, 76, 83, 82, 80, 80, 76, 76, 78, 78, 82, 84, 86, 99,101,103,104,110, 99, 70, 80],
   [ 77, 74, 82, 82, 79, 79, 74, 75, 75, 74, 79, 82, 82, 99, 99,103,102, 99,110, 66, 79],
   [ 73, 70, 76, 78, 76, 77, 73, 74, 75, 73, 75, 74, 71, 63, 67, 67, 67, 70, 66,110, 75],
   [ 99, 98,101,105,105,105, 96, 95, 97, 93,100, 97, 92, 77, 79, 80, 80, 80, 79, 75,110]]
g=networkx.Graph()
for i,p in enumerate(h):
  g.add_node(p)
  for j,q in enumerate(h[:i]):
    g.add_edge(p,q,weight=w[i][j]/min(w[i][i],w[j][j]))
c=networkx.spectral_layout(g,dim=3)
p=numpy.array([c[x] for x in h])
f=scatter_3d(x=p[:,0],y=p[:,1],z=p[:,2],text=h,opacity=0.5,labels={"x":"","y":"","z":""},width=1600,height=1600)
q={"tickfont":{"color":"white"}}
f.update_scenes(xaxis=q,yaxis=q,zaxis=q)
f.show()
```

私(安岡孝一)の手元では、以下の3D図が出力された。

![ainu-dialect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/42ac245c-7843-daad-9a4b-aa217de0a43a.png)

なかなか刺激的な図だ。マウスで回転や拡大もできるので、ノードが集まっているあたりを拡大してみよう。

![ainu-dialect-zoom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/1beb33f4-ef25-347a-db96-1b839ab7afdb.png)

まあ、悪くない結果だ。ただし、この3D図を鵜呑みにするのは危険だ。表6の方言語彙類似度をBag of Wordsの視点から見ると、このSzymkiewicz-Simpson係数(もどき)は、単語ベクトルのコサイン類似度とほぼ同等であり、逆数を取ろうが1から引こうが距離の定義(三角不等式)を満たさない。3次元のユークリッド空間に落とし込むのなら、Szymkiewicz-Simpson係数(あるいはJaccard係数)を使うのは危険で、たとえば各方言(21地点)に出現する全単語を単語ベクトルの形で記述し、それらの単語ベクトルをいったん20次元に落とした上で、さらに次元圧縮で3次元へと落とす(あるいは3次元断面で切って見る)というのが常道だろう。うーん、言うのは簡単だが、さすがに手間がかかるなあ。