2019年9月6日金曜日

RFIDの読取結果を機械学習でクラスタリングしてみた

RFIDタグを読むといったら、多くの場合、その場にあるモノを自動で識別することを指していると思います。一方で、UHF帯のRFIDを使って、移動の向きであったり、モノの位置であったりを検出するハードウェアや、ソフトウェア的に高精度に向きや位置を検出する技術(RFLocus, Impinj ItemSense)が出てきています。

このように今後はUHF帯RFIDを使って、移動の向きや位置を検出するといった用途が増えていくのではと思われます。そこで、おおざっぱにでも近くに置かれたタグ同士を判別できないかを、読み取ったICタグの時系列データを使って、KMeansでクラスタリングして試してみました。
(いろいろ書いてますが、初心者がPythonの機械学習に触れてみた的な記事です)

今回使ったもの

(*) 結果的にはMANICAコレクタでよかったかも。

ICタグの読取手順

まず、ICタグを5枚ずつ、数十㎝離して4箇所に配置しました。読取は各箇所の上空にRF Blasterを順番にかざすような感じで読み取りました。(なんだか恣意的ですが)各箇所には上位ビットが同じで下位のシリアルが1~5となっているものをひとまとめにして置いてあります。

Microsoft Azure Notebooks

今回機械学習でクラスタリングしてみるのに、Microsoft Azure Notebooksを使いました。使ったプロジェクトはこちらです。RF Blasterを使って読み取った結果がこちらのCSVファイルになります。読取時刻にタグIDとRSSI, Phaseの値が並んでいる形になります。

こちらが使ったNotebookになります。初めに、pandas, numpy, KMeansをimportしています。次にDataFrameにデータを取込んで加工しています。そのあと、下記コードで時系列データを毎秒のRSSI値の平均をとり、タグID単位に集計しています。表示されるタグIDは上から順に5枚ずつ同じ箇所に置いてあります。

pvT = df.reset_index().pivot_table(index=[pd.Grouper(freq='1s', key='DateTime')], columns=["TagID"], values="RSSI", aggfunc=np.mean).fillna(0).T

集計したデータをKMeansでクラスタリングしてみたのが下記のコードになります。

pred = KMeans(n_clusters=4).fit_predict(pvT.values)

結果を見てみると、

print(pred)
[2 2 2 2 2 3 1 1 3 3 1 1 1 3 1 0 2 0 0 2]

先頭から5個ずつ順に同じ箇所にタグを置いたので、同じ数字が5個ずつ並んでほしいところですが、そうなっていません。
同じように、Phase値の平均をとってクラスタリングした結果を見てみます。

pvPhaseT = df.reset_index().pivot_table(index=[pd.Grouper(freq='1s', key='DateTime')], columns=["TagID"], values="Phase", aggfunc=np.mean).fillna(0).T
predPhase=KMeans(n_clusters=4).fit_predict(pvPhaseT.values)
print(predPhase)
[3 3 3 3 3 0 2 2 0 0 2 2 2 0 2 1 1 1 1 3]

こちらも残念ながらうまく並んでいません。そもそも秒単位に平均をとることに意味があるのかわからなくなってしまったので、箱ひげ図を出力してみました。
(データの加工はもうちょっとやり方ありそうですが、思いつかなかったので、適当です)



重なっていてよく分かりませんが、秒単位で集計してもわりと振れ幅があって、平均取ることに意味がなさそうです。同じくPhaseだとこんな感じです。そもそもどういう意味がある数値なのかすら分かってないですが、これも平均取ることの意味がないのかもしれません。


平均ではうまくいかなかったので、もっと単純に秒単位の読取回数でクラスタリングしてみました。

pvCountT = df.reset_index().pivot_table(index=[pd.Grouper(freq='1s', key='DateTime')], columns=["TagID"], values="RSSI", aggfunc=np.count_nonzero).fillna(0).T
predCount = KMeans(n_clusters=4).fit_predict(pvCountT.values)
print(predCount)
[0 0 0 0 0 2 2 2 2 2 1 1 1 1 1 3 3 3 3 3]

これだと、きれいに5個ずつ同じクラスタと判定されました。初期値を変えて、何回かやってみましたが、いずれもうまく判定されました。

まとめとこれから


とりあえず、少数のタグを使ったきれいなデータであれば、うまいこと判別できることが分かりました。次はもう少し実際に近い(いくつかの箱にもっと多くのタグが入っている)イメージで試してみたいと思います。あとは、あらかじめ位置の決まったタグ(いわゆる位置タグ)を教師として、クラス分類してみても面白いかもしれません。

最終的にはUHF帯RFIDを使った棚卸の場面で、庫内のどこかで読んだのだけれど、特定のタグIDの商品がどこにあるか分からないという場面でモノ探しに役立てるようにしたいです。

1 件のコメント:

  1. ある時系列データ中の期間で読まれた位置タグの個数をクラスタ数、初期のクラスタ中心を位置タグとすればもしかしたら、うまく行く?

    返信削除