GMTが使えない

先日まで機嫌よく動いていたGMT4.5.13が突然

psbasemap: error while loading shared libraries: libnetcdf.so.6: cannot open shared object file: No such file or directory

と、動かなくなりました。

whereis libnetcdf.so.6

で libnetcdf.so.6を調べると、

libnetcdf.so.5とlibnetcdf.so.7は/usr/libの下に存在するけれど6は有りませんでした。

GMTのソースディレクトリに戻って

sudo ./install_gmt4.sh

を叩いたら、何とか復旧しました。

そろそろGMTのバージョンを上げて置く方がよいかも知れません。

 

 

 

USB2-HUB4XA-BKについて

 システムトークスのSUGOI HUB4Xシリーズ という凄いネーミングのUSBハブを使ってみました。

 うたい文句は安定した高出力の電源供給ということですが、実はソフトによってパソコンから電源オンオフができるというのも特徴です。

 http://www.gniibe.org/oitoite/ac-power-control-by-USB-hub/hub-ctrl.c

を入手してコンパイルすると、

 「usb.hがありません」

と文句を言われました。

 ふむふむ、usb.h は libusb-dev パッケージに含まれているとな…。

 sudo apt-get install libusb-dev で無事入手しました。

 さて再度コンパイルすると、

/tmp/ccEdGPrr.o: 関数 `hub_port_status' 内:
hub-ctrl.c:(.text+0xb1): `usb_control_msg' に対する定義されていない参照です
/tmp/ccEdGPrr.o: 関数 `usb_find_hubs' 内:
hub-ctrl.c:(.text+0x37a): `usb_get_busses' に対する定義されていない参照です
hub-ctrl.c:(.text+0x459): `usb_open' に対する定義されていない参照です
hub-ctrl.c:(.text+0x4b4): `usb_control_msg' に対する定義されていない参照です
hub-ctrl.c:(.text+0x639): `usb_close' に対する定義されていない参照です
hub-ctrl.c:(.text+0x769): `usb_close' に対する定義されていない参照です
/tmp/ccEdGPrr.o: 関数 `main' 内:
hub-ctrl.c:(.text+0xb67): `usb_init' に対する定義されていない参照です
hub-ctrl.c:(.text+0xb6c): `usb_find_busses' に対する定義されていない参照です
hub-ctrl.c:(.text+0xb71): `usb_find_devices' に対する定義されていない参照です
hub-ctrl.c:(.text+0xc13): `usb_open' に対する定義されていない参照です
hub-ctrl.c:(.text+0xce4): `usb_control_msg' に対する定義されていない参照です
hub-ctrl.c:(.text+0xd38): `usb_close' に対する定義されていない参照です
collect2: error: ld returned 1 exit status

 なんだか更に一杯怒られました。結構時間を掛けて調べたところ、libusb.aなどが/user/libの下ではなく、/usr/lib/x86_64-linux-gnu の下に落とされていたことが判明し、ようやく解決です。

 適切なbus番号を$ bus、device番号を$ deviceとすると、

sudo ./hub-ctrl -b ${ bus } -d ${ device }  -P 1 -p 0

 で1番ポート(左端のダウンストリームポート)の電源が遮断されました。

なるほど、これはスゴイかも知れません。

 

 ところで、hub-ctrl.cを公開してくれているのは、システムトークスともNECとも関係なさそうな方ですね。ということは一般にUSBハブに対して hub-ctrl.c を使用すると、電源のオンオフが可能になるのではないでしょうか。

 と考えて十年来使用している ArvelのH428-GNというハブでも同じことを試してみましたが、結果は全くの不発でした。上手くゆく製品とそうでない製品があるということなのでしょうね。

 

 

 

xmlのmysqlへの登録

前回、取得したRSSxml形式でした。

xmlならばxpathコマンドで個々の要素に分解することができます。

具体的には

 title=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//title/text()"  2>/dev/null `

 で変数titleに上から$item番目の見出しを代入することができます。

データベース名life_logにテーブルを作成しました。フィールドは

title 見出し、link 記事本文のURL、guid 同左、pubDate 配信日時、description 記事概要、insertDate データベース登録日時

としました。

MYSQLにinsertで登録した後、

select title,min(pubDate),max(insertDate) from nhk_main group by title order by max(insertDate)-min(pubDate) desc limit 20;

で過去24時間のうちに長い時間掲載されていたニュース上位20を検索してみました。

インドネシアオラウータンの話題が、最も長い時間掲載されていたみたいです。

 

  見出し 配信開始日時 掲載終了
1 珍しい白いオランウータン保護 インドネシア 2017-05-16 22:05:00 2017-05-17 09:00:00
2 眞子さま 同級生とご婚約へ 2017-05-16 19:01:00 2017-05-17 05:00:00
3 自衛隊機墜落 発見の4人は自衛隊員 全員死亡 2017-05-16 18:21:00 2017-05-17 04:00:00
4 文科省の審議会 新設獣医学部に「課題あり」と報告 2017-05-16 21:32:00 2017-05-17 04:00:00
5 複数ワクチン混ぜる誤った方法で乳幼児に予防接種 2017-05-16 18:42:00 2017-05-17 01:00:00
6 テニス不正監視団体 日本の元プロテニス選手を永久資格停止 2017-05-16 22:58:00 2017-05-17 04:00:00
7 北朝鮮 安保理声明に反発「全面的に排撃する」 2017-05-16 22:03:00 2017-05-17 01:00:00
8 眞子さまご婚約へ ゆかりの人から祝福の声 2017-05-17 05:06:00 2017-05-17 11:00:00
9 眞子さまご婚約へ 小室さん「時期来たら改めて説明」 2017-05-17 10:17:00 2017-05-17 15:00:00
10 野党4党 金田法相の不信任決議案を提出 2017-05-17 10:18:00 2017-05-17 15:00:00
11 高浜原発4号機 きょう 再稼働へ 2017-05-17 06:28:00 2017-05-17 11:00:00
12 「大学入学共通テスト」最終案まとまる 記述式も 2017-05-16 11:43:00 2017-05-16 16:00:00
13 トランプ大統領がロシアに機密情報漏えいか 米紙報道 2017-05-16 11:49:00 2017-05-16 16:00:00
14 大規模サイバー攻撃 北朝鮮ハッカー集団使用のソフトと類似 2017-05-16 13:53:00 2017-05-16 18:00:00
15 「乃木坂46」ファンの教師が偽造学生証を提示か 2017-05-16 12:00:00 2017-05-16 16:00:00
16 自民 二階幹事長 中国 習主席と会談 北朝鮮問題で連携を 2017-05-16 14:05:00 2017-05-16 18:00:00
17 国連安保理 北朝鮮ミサイル発射で緊急会合へ 2017-05-17 01:10:00 2017-05-17 05:00:00
18 「テロ等準備罪」野党4党が法相不信任決議案提出へ 2017-05-17 05:11:00 2017-05-17 09:00:00
19 トランプ大統領 ロシアに情報で与党からも問題視する意見 2017-05-17 06:16:00 2017-05-17 10:00:00
20 自衛隊機墜落 ボイスレコーダー発見急ぎ事故原因究明へ 2017-05-17 07:23:00 2017-05-17 11:00:00

 このスクリプトも前回のcrontabに登録してしまうと、1時間に1回自動的にRSSを取得してMYSQLに登録してくれるようになります。

#!/bin/bash
mysql << _SQL_
 create database if not exists life_log default character set utf8;
 use life_log;
 create table if not exists nhk_main(
  title varchar(200),
  link varchar(100),
  guid varchar(100),
  pubDate datetime,
  description varchar(1500),
  insertDate datetime,
  effect int default 1,
  comment varchar(20)
 );
_SQL_

echo `date -d "$date"` の配信です
   
file=~/nhk/`date -d "$date" '+%m%d%H%M'`.xml
num_item=`cat $file | grep \<item\> | wc -l`
for ( ( item=1; item<=${num_item}; item++ ) )
do
 title=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//title/text()"  2>/dev/null |\
   nkf `
 link=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//link/text()"  2>/dev/null `
 guid=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//guid/text()"  2>/dev/null `
 pubDate=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//pubDate/text()"  2>/dev/null `
 pubDate=`date -d "${pubDate}" +"%Y-%m-%d %H:%M"`
 description=`\
  cat $file |\
   xpath -q -e "//item[${item}]" 2>/dev/null |\
   xpath -e "//description/text()"  2>/dev/null `
 mysql life_log << _SQL_
  insert into nhk_main(title,link,guid,pubDate,description,insertDate)
  value("${title}","${link}","${guid}","${pubDate}","${description}","${date}");
_SQL_
done

RSSの取得

多くのニュースサイトはRSSも配信しています。

フリーのRSSリーダーなんかで取得することもできますが、色々加工してみたいので、直接取りにゆくことを試みました。

NHKオンラインのニュースを使わせてもらいました。

#!/bin/bash
<<_NHKニュース_
cat0    NHKニュース 主要ニュース
cat1    NHKニュース 社会
cat3    NHKニュース 科学・医療
cat4    NHKニュース 政治
cat5    NHKニュース 経済
cat6    NHKニュース 国際
cat7    NHKニュース スポーツ
cat2    NHKニュース 文化・エンタメ
cat-live    NHKニュース LIVEニュース
_NHKニュース_

cate=cat0
file=`date "+%m%d%H%M"`.xml
wget  http://www3.nhk.or.jp/rss/news/${cate}.xml -O- > ~/nhk/$file
 

 実行すると、実行時刻に応じたファイル名($file)を付けて所望のフォルダーに保存されます。

恥ずかしながらRSSって下図のようなxml形式で書かれているというのは、今回初めて知りました。

f:id:S_E_Hyphen:20170516145601p:plain

 

# m h dom mon dow command
*/10 * * * * /home/user/bin/getrss_NHK >/dev/null 2>&1

上記のコマンドを平のユーザーでcrontabに登録すれば(sudoである必要はない)、10分毎のRSSが自動的に取得されてファイルに保存されます。

 

中間層ふたたび

1段目のノード数は0
2段目のノード数は0
3段目のノード数は2
トレーニングを10000回繰り返すと誤差関数は302.798157となりました
<matplotlib.collections.PathCollection at 0x6af2b10>

これは手も足も出ませんね。

 


 

1段目のノード数は0
2段目のノード数は2
3段目のノード数は2
トレーニングを10000回繰り返すと誤差関数は255.961716となりました
<matplotlib.collections.PathCollection at 0x70a8d90>

中間層を2段にしましたが、イマイチです。

 


 

1段目のノード数は0
2段目のノード数は2
3段目のノード数は10
トレーニングを10000回繰り返すと誤差関数は36.078690となりました
<matplotlib.collections.PathCollection at 0x6ccdc50>

最終の中間層のノード数を増やすと結構良くなりました。

 


 

1段目のノード数は2
2段目のノード数は2
3段目のノード数は10
トレーニングを10000回繰り返すと誤差関数は32.553638となりました
<matplotlib.collections.PathCollection at 0x6de0f90>

中間層を3段にすると悪化しました。

 

1段目のノード数は0
2段目のノード数は0
3段目のノード数は25
トレーニングを10000回繰り返すと誤差関数は28.560705となりました
<matplotlib.collections.PathCollection at 0x7c49ad0>

なぁんだ。これでもいけるんじゃん。

隠れ層(中間層)を用いた3色分類

前回と同様の手順で下図のように塗り分けられたデータを分類してみました。

f:id:S_E_Hyphen:20170503085651p:plain

ですよねぇ。

青点が両側に分離されてしまってますから、緑や赤との境界が決まりません。

「全部、青」と言われれば「そうなのかなぁ」といったところです。

 

このようなデータでも「隠れ層(中間層)」と呼ばれる未知数を追加するだけで分類が可能となります。

num_units = 2

x=tf.placeholder(tf.float32,[None,1])

w1=tf.Variable(tf.truncated_normal([1,num_units]))
b1=tf.Variable(tf.zeros([num_units]))
hidden1=tf.nn.relu(tf.matmul(x,w1)+b1)
               
w0=tf.Variable(tf.zeros([num_units,3]))
b0=tf.Variable(tf.zeros([3]))
f=tf.matmul(hidden1,w0)+b0
p=tf.nn.softmax(f)

t=tf.placeholder(tf.float32,[None,3])
loss=-tf.reduce_sum(t*tf.log(tf.clip_by_value(p,1e-10,1.0)))
train_step=tf.train.AdamOptimizer().minimize(loss)

 

赤で示した未知数w1、b1とプレースホルダーxから算出されるhidden1というのが隠れ層(中間層)と呼ばれるものです。前回出てきた一次関数f(w0,b0)の計算からソフトマックス関数の適用までと、瓜二つの繰り返しのように見えます。

 

このトレーニングを十分に繰り返したあとのhidden1の値の分布を示します。

f:id:S_E_Hyphen:20170503092230p:plain

num_units=2としているので、hidden1は2次元となっています。横軸はhidden1[ 0 ]、縦軸はhidden1[ 1 ]です。

-5<=x<=5で50分割したものを入力して計算したhidden1の値を打点しました。x=-5はhidden1=(0,0)に変換されるようです。逆にx=+5はhidden1=(15,25)に変換されます。

すなわち、この中間層はX軸を2次元上の曲線(あるいは2つの線分)に変換していたのです。

こうなってしまえば、正負で分離されていたと思われた青点も平面上の一つの直線の同じ側として一括りに扱うことが可能となります。

f:id:S_E_Hyphen:20170503093751p:plain

そうなるように適切にw0とb0を求めて、青赤緑それぞれの確率を計算して描画します。

f:id:S_E_Hyphen:20170503100607p:plain

隠れ層(中間層)を使用することで、複雑な領域分けが可能となりました。


 
# coding: utf-8

# In[ ]:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import multivariate_normal, permutation
import pandas as pd
from pandas import DataFrame, Series

np.random.seed(20170426)


# In[ ]:

num_train=300
x=np.random.rand(num_train)*10-5
t=np.zeros( (num_train,3) )
df=DataFrame(np.c_[x,t],columns=['x','blue','red','green'])

for i in range(num_train):
    if df.x[i]<-2.25:
        df.blue[i]=1
    elif df.x[i]>2.25:
        df.blue[i]=1
    elif df.x[i]<0:
        df.red[i]=1
    else:
        df.green[i]=1
#データフレームから行列変換します。train_tはOne-Hot表現にしています。
train_x=df['x'].as_matrix().reshape([len(df),1])
train_t=df[ ['blue','red','green'] ].as_matrix().reshape([len(df),3])


# In[ ]:

fig = plt.figure(figsize=(3,3))
subplot = fig.add_subplot(1,1,1)
subplot.set_xlim([-5,5])
subplot.set_ylim([-1,1.5])
red=df[df.red==1]
subplot.scatter(red.x,-0.5*red.red+0.05, color='r', marker='o')
blue=df[df.blue==1]
subplot.scatter(blue.x,-0.5*blue.blue-0.05, color='b', marker='o')
green=df[df.green==1]
subplot.scatter(green.x,-0.5*green.green, color='g', marker='o')


# In[ ]:

num_units = 2

x=tf.placeholder(tf.float32,[None,1])

w1=tf.Variable(tf.truncated_normal([1,num_units]))
b1=tf.Variable(tf.zeros([num_units]))
hidden1=tf.nn.relu(tf.matmul(x,w1)+b1)
               
w0=tf.Variable(tf.zeros([num_units,3]))
b0=tf.Variable(tf.zeros([3]))
f=tf.matmul(hidden1,w0)+b0
p=tf.nn.softmax(f)

t=tf.placeholder(tf.float32,[None,3])
loss=-tf.reduce_sum(t*tf.log(tf.clip_by_value(p,1e-10,1.0)))
train_step=tf.train.AdamOptimizer().minimize(loss)


# In[ ]:

sess=tf.Session()
sess.run(tf.initialize_all_variables())


# In[ ]:

i=0
#10000回トレーニングを実施します。
for _ in range(10000):
    i += 1
    sess.run(train_step,feed_dict={x:train_x, t:train_t})
    if i%1000==0:
        loss_var=sess.run(loss,feed_dict={x:train_x, t:train_t})
        print '%d:loss=%f' % (i,loss_var)


# In[ ]:

# 2ノードの隠れ層(中間層)で表現される仮想平面を描画します。
test_x=np.linspace(-5,5,50).reshape([50,1])
h_val=sess.run(hidden1,feed_dict={x:test_x})
plain=DataFrame(np.c_[test_x,h_val],columns=['x','x1','x2'])

p_val=sess.run(p,feed_dict={hidden1:h_val})
line=DataFrame(np.c_[h_val,p_val],columns=['x1','x2','blue','red','green'])

fig = plt.figure(figsize=(10,3))
subplot = fig.add_subplot(1,3,1)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(line.x1,line.x2, s=10, c=line.blue, cmap='Blues')

subplot = fig.add_subplot(1,3,2)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(line.x1,line.x2, s=10, c=line.red, cmap='Reds')

subplot = fig.add_subplot(1,3,3)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(line.x1,line.x2, s=10, c=line.green, cmap='Greens')


# In[ ]:

# 仮想平面と青赤緑の関係です。
plane=[]
for x2 in np.linspace(0,25,50):
    for x1 in np.linspace(0,25,50):
        plane.append( (x1,x2) )
p_val=sess.run(p,feed_dict={hidden1:plane})
image=DataFrame(np.c_[plane,p_val],columns=['x1','x2','blue','red','green'])

fig = plt.figure(figsize=(10,3))
subplot = fig.add_subplot(1,3,1)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(image.x1,image.x2, s=10, c=image.blue, cmap='Blues')

subplot = fig.add_subplot(1,3,2)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(image.x1,image.x2, s=10, c=image.red, cmap='Reds')

subplot = fig.add_subplot(1,3,3)
subplot.set_xlim([-1,25])
subplot.set_ylim([-1,25])
subplot.scatter(image.x1,image.x2, s=10, c=image.green, cmap='Greens')


# In[ ]:

# テストデータとして-5から5を50分割したtest_xを作成します
# このテストデータで、青赤緑それぞれの確率を計算して描画します
test_x=np.linspace(-5,5,50).reshape([50,1])
p_val=sess.run(p,feed_dict={x:test_x})
line=DataFrame(np.c_[test_x,p_val],columns=['x','blue','red','green'])

fig = plt.figure(figsize=(3,3))
subplot = fig.add_subplot(1,1,1)
subplot.set_xlim([-5,5])
subplot.set_ylim([-1,1.5])
subplot.plot(line.x,line.blue,color='b')
subplot.plot(line.x,line.red,color='r')
subplot.plot(line.x,line.green,color='g')

red=df[df.red==1]
subplot.scatter(red.x,-0.5*red.red+0.05, color='r', marker='o')
blue=df[df.blue==1]
subplot.scatter(blue.x,-0.5*blue.blue-0.05, color='b', marker='o')
green=df[df.green==1]
subplot.scatter(green.x,-0.5*green.green, color='g', marker='o')

 

 

 

tensorflowによる3色分類の実施

ソフトマックス関数で3色の分類を実施してみました。


 

お決まりのモジュールのインポートです。

In [1]:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from numpy.random import multivariate_normal, permutation
import pandas as pd
from pandas import DataFrame, Series

np.random.seed(20170426)
 

平均値-1.5、分散1.3の正規乱数を100個発生させて青のデータセットとします。train_tは[1,0,0]となっています。

平均値0.5、分散0.8の正規乱数を100個発生させて赤のデータセットとします。train_tは[0,1,0]となっています。

平均値3.5、分散1.2の正規乱数を100個発生させて緑のデータセットとします。train_tは[0,0,1]となっています。

permutationを使って順番を入れ替えています。

In [2]:
#青のデータセット
num_train0=100
x0=np.random.normal(-1.5,1.3,num_train0)
t0=np.zeros((num_train0,3))
df0=DataFrame(np.c_[x0,t0],columns=['x','blue','red','green'])
df0['blue']=1

#赤のデータセット
num_train1=100
x1=np.random.normal(0.5,0.8,num_train1)
t1=np.zeros((num_train1,3))
df1=DataFrame(np.c_[x1,t1],columns=['x','blue','red','green'])
df1['red']=1

#緑のデータセット
num_train2=100
x2=np.random.normal(3.5,1.2,num_train2)
t2=np.zeros((num_train2,3))
df2=DataFrame(np.c_[x2,t2],columns=['x','blue','red','green'])
df2['green']=1
#繋ぎあわせて一つのデータフレームにします
df=pd.concat([df0,df1,df2],ignore_index=True)
df=df.reindex(permutation(df.index)).reset_index(drop=True)
#データフレームから行列変換します。train_tはOne-Hot表現にしています。
train_x=df['x'].as_matrix().reshape([len(df),1])
train_t=df[['blue','red','green']].as_matrix().reshape([len(df),3])
 

冗長ですが散布図を描いてみました。縦軸に意味はありません。

値の小さい方から青→赤→緑となっていますが、その境目は渾然としています。

この境界をソフトマックス関数で決定しようというのが狙いです。

In [3]:
fig = plt.figure(figsize=(3,3))
subplot = fig.add_subplot(1,1,1)
subplot.set_xlim([-5,5])
subplot.set_ylim([-1,1.5])
red=df[df.red==1]
subplot.scatter(red.x,-0.5*red.red+0.05, color='r', marker='o')
blue=df[df.blue==1]
subplot.scatter(blue.x,-0.5*blue.blue-0.05, color='b', marker='o')
green=df[df.green==1]
subplot.scatter(green.x,-0.5*green.green, color='g', marker='o')
Out[3]:
<matplotlib.collections.PathCollection at 0x6d28150>
 
 

xは300×1の行列です。300はデータセットの標本数です。

青、赤、緑の3つに分類するので、wとw0は3列となります。これは未知数です。

wとw0に適当な数値を仮定してf=x*w+w0という一次関数を計算します。

これにソフトマックス関数を適用することで、仮定したw,w0に対応する確率pを求めます。

プレースホルダーtにはtrain_tが代入されることとなります。

例えば実際に「青」であった場合t=[1 0 0]です。

t*log(p)を計算することにより、仮定したw,w0により「青」と推定された確率p[0]だけが意味を持つこととなります。

これの総和(reduce_sum)が最も良い値となるようにトレーニングを実施します。

In [4]:
x=tf.placeholder(tf.float32,[None,1])
w=tf.Variable(tf.zeros([1,3]))
w0=tf.Variable(tf.zeros([3]))
f=tf.matmul(x,w)+w0
p=tf.nn.softmax(f)

t=tf.placeholder(tf.float32,[None,3])
loss=-tf.reduce_sum(t*tf.log(p))
train_step=tf.train.AdamOptimizer().minimize(loss)
In [5]:
sess=tf.Session()
sess.run(tf.initialize_all_variables())
 

10000回トレーニングを実施します。

テストデータとして-5から5を50分割したtest_xを作成しました。

このテストデータで、青赤緑それぞれの確率を計算して描画します

In [6]:
#10000回トレーニングを実施します。
for _ in range(10000):
    sess.run(train_step,feed_dict={x:train_x, t:train_t})
    
# テストデータとして-5から5を50分割したtest_xを作成します
# このテストデータで、青赤緑それぞれの確率を計算して描画します
test_x=np.linspace(-5,5,50).reshape([50,1])
p_val=sess.run(p,feed_dict={x:test_x})
line=DataFrame(np.c_[test_x,p_val],columns=['x','blue','red','green'])

fig = plt.figure(figsize=(3,3))
subplot = fig.add_subplot(1,1,1)
subplot.set_xlim([-5,5])
subplot.set_ylim([-1,1.5])
subplot.plot(line.x,line.blue,color='b')
subplot.plot(line.x,line.red,color='r')
subplot.plot(line.x,line.green,color='g')

red=df[df.red==1]
subplot.scatter(red.x,-0.5*red.red+0.05, color='r', marker='o')
blue=df[df.blue==1]
subplot.scatter(blue.x,-0.5*blue.blue-0.05, color='b', marker='o')
green=df[df.green==1]
subplot.scatter(green.x,-0.5*green.green, color='g', marker='o')
Out[6]:
<matplotlib.collections.PathCollection at 0x6d22710>
 
 

値の小さいうち、例えば-5から-3位までは青がほぼ100%で、赤や緑は0%です。

実際そのような値の赤点や緑点は存在しません。

赤点が存在し始める(より、やや小さな)-2位から赤の確率が上昇してきます。

同時に青の確率が下降し、概ね-0.2で両者は交差します

値の大きな青もあれば値の小さな赤もあるのですが、その境界は-0.2であったと断言することができるわけです。

同様に赤と緑の境界は+1.8であったと言い切れます。

このようにソフトマックス関数を適用することで渾然としたデータの境界を決定することが可能となります。