競プロとか

tobii xr sdkのGetting Startedが動かない時の解決策

【環境】

Unity: 2020.3.12f1
HMD: VIVE Pro Eye
Tobii XR SDK: 3.0.0.178
VIVE SRanipal SDK: 1.3.2.0

【問題】

Getting Startedを動かした際に、適切に視線の情報を取得できない
具体的にはHMDの中心座標が視線の情報となっていた

【解決策】

ちゃんと必要なものがインポートされているか確認すること
SRanipalをインストールして満足して、importするのを完全に失念してた
f:id:Radperia:20210621112220p:plain

ちなみにUnity側だとこれに関連したエラーは生じない

var eyeTrackingData = TobiiXR.GetEyeTrackingData(TobiiXR_TrackingSpace.World);
if (eyeTrackingData.GazeRay.IsValid)
{
  hoge
}

とか書くだろうけど、IsValidが常にFalseになるだけなはず

【余談】

tobii側のサイトだけ見てたのも不味かった vr.tobii.com

UnityにおけるVIVE Pro Eye開発環境作成

【やること】

とりあえず下記サイトのStep5まで従う
vr.tobii.com

ただしSampleには存在しているけど、所在が分からないものもある
TobiiXR InitializerとかXR Rigとか…… f:id:Radperia:20210620150337p:plain

【TobiiXR Initializer】

Packages/Tobii XR SDK/Runtime/Prefabs にある
ドラッグして持って来よう

【XR Rig】

自分で作ろう
Create EmptyでXR Rig, Camera Offsetを作成し、直下にMain Camera設置 Main CameraにAdd Component -> Tracked Pose Driver f:id:Radperia:20210620151209p:plain

一応SampleのMain CameraにはFlare Layerが追加されてるけど
正直見にくくなるし使いづらいから入れなくても良いと思ってる

最低限この2つがあれば大丈夫

hoge

追記するかも。

VIVE_SRanipalInstallerにてError 1001が生じる場合の解決策

【経緯】

Vive Cosmos Elite + Pupil Labsにて瞳孔径関連の研究を進めていたが
あまりにも測定精度が悪いためVive Pro Eyeに乗り換えた次第

【事象】

本体セットアップ後にSRanipalを導入する段階でError 1001に遭遇 f:id:Radperia:20210620142433p:plain

【原因】

確実にこれ、だとは言えないがVive Cosmos Eliteを
事前にセットアップしてたことに起因すると考えている
VIVEのコミュニティフォーラムにて、片方のパソコンでは上手くいったが、
もう片方では上手くいかなかったとの報告がある
恐らく既にVIVE製品のセットアップが終了していた方のパソコンで
不具合が出たものと勝手に考えている
forum.vive.com

【解決策】

デフォルトのインストール先が "C:/Program Files/VIVE"となっていたが、
"C:/Program Files(x86)/VIVE"にて既にインストールされていることが確認できた
念のためx86側のフォルダからアンインストールし、
再インストールすることでエラーは生じなくなった

【おまけ】

公式サポートの

システムダッシュボードからVIVE Pro Eyeを選択します

の意味が分からなかった、システムダッシュボードとは……? www.vive.com

結局のところコントローラーから起動できるメニューの下側のことらしい、知らんかった f:id:Radperia:20210620143428p:plain

SIGNATE Student Cup 2020 参加記録

参加経緯

先日Kaggleの"SIIM-ISIC Melanoma Classification"に参加し銀メダルを獲得したが, 自分の力でどこまで行けるのかを測ってみたかった.
そんな中でSIGNATEで学生限定コンペが開催されているとの噂を聞き参加した次第.

コンペ概要

Trainデータ数 2931 Testデータ数 1743
英文からData Scientist, Machine Learning Engineer, Software Engineer, Consultantを推測するモデルの作成.
俗にいうNLP (Natural Language Processing)である. 評価は"macro-F1"であった.

解法

無論NLPに関しては何も知らなかった.
Kaggleのnotebookを読み漁り, n_gramやらtf-idf等の考え方があることを知った.

n-gram

n-gramはnに自然数が入る. 1, 2, 3はuni-gram, bi-gram, tri-gramと呼ばれる.
4以降はそのままfour-gram, five-gramとなる.
unigramは単一の単語, つまり英語であれば1単語ずつ,
bigramは2連続の単語, trigramは3連続の単語を示す.
これの何が良いかと言うと, 各文章中から特定の表現が頻出して現れる様であれば
それを特徴量として区別することが可能となるのである(そう理解している).

tf-idf

tf-idfは"Term Frequency"(TF)と"Inverse Document Frequency"(IDF)を組み合わせたものである.
TFに関しては読んで字のごとく, 特定の単語の文書内の出現頻度を数値化する.
IDFはある単語が出てくる文書の頻度の逆数である.
TFについては直感的に分かるが, IDFは微妙に何を言ってるのか分かりにくい.
簡単に言い換えると, 英語であれば冠詞を主として, 多くの文章中に登場する単語は特徴として不適であるということである.

つまり, 文章中のn-gramを調査し, tf-idfによって特徴量を生成するというのが基本の流れである.
nの選定に関してはtrigramまで調べたところ文章がそこまで長くないこともあり,
あまり有意な特徴がこれ以上でるとは考えられないため, trigramで止めた.
tf-idfはsklearnのものを使用した. とても分かりやすく使えるので楽であった.

提出したファイルのsolutionは次の通りである.

  • model 1

    • TfidfVectorizer: analyzer='word' max_features=20000

    • TfidfVectorizer: analyzer='char' ngram_range=(2,4) max_features=40000

    • Logistic Regression: C=10 solver='sag' class_weight='balanced' max_iter=20000

  • model 2

    • 特徴量抽出は同じ

    • Random Forest: n_estimators=200, class_weight='balanced'

  • model 3

    • TfidfVectorizer: analyzer='word' max_features=20000

    • TfidfVectorizer: analyzer='char' ngram_range=(2,5) max_features=60000

    • Random Forest: n_estimators=200, class_weight='balanced'

この3つのモデルをvotingによってアンサンブルした.
ただ後半適当なメモ書きしか残してないため参考程度である.
もっと丁寧に記録をつけるべきだった……

成績

最終的にPublic LB: 46位(0.4729881), Private LB: 32位(0.4671081)となりギリギリ上位10%入れないくらいであった.
実はSVC, Logistic Regression, Random Forestでスタッキングしたモデルも試しており, そちらはPublic: 0.4635398, Private: 0.4837021と16位程度の成績を残していた.
スタッキングを信じれば良かったが, 提出ファイルが1つとなるとそうも行かないのが現実であった.
とはいえ, 全く分からなかったNLPの分野でも比較的良い成績を残せたのは自信になった. 何より楽しかった.
f:id:Radperia:20200829204359j:plain

SIIM-ISIC Melanoma Classification 参加記録

Kaggleを始めた

前々から気にはなっていたが、機械学習に興味が持てなく競プロに熱を割いていた
ただその競プロも緑帯に入ってから伸び悩み、楽しくなくなっていた
もっとも3週間の予定で入っていたインターンがコロナで消滅して、暇になったから丁度良いと思って始めた

コンペ概要

本コンペは数ある画像データから、メラノーマ(悪性黒色腫)であるかどうかの確率を推定するものである。 コンペに出たことが無かった為、テーブルデータが出来れば良かった が無いものは無いので、ある程度参加者が多くnotebookが参考になりそうな、メラノーマコンペを選んだ次第

解法

何も分からないから、ひたすら公開されているnotebookを読み解いた

www.kaggle.com

www.kaggle.com

www.kaggle.com

上記、3つのnotebookを中心的に読み解いた

その中でも一番下の"Analysis of Melanoma Metadata and EffNet Ensemble"は、メタデータの解析を非常に丁寧に行っており参考になった

そのnotebook内ではXGBを使用しpublic score: 0.8484もの精度を出していた

全体を通じて、外部からデータを引き込み更にaugmentさせ、EfficientNetに流し込む流れが主流である(多分)

但しnotebookによって使用するEfficientNet B0 ~ B7の選択が異なり、何に依存しそもそもB*とは何なのか(スケーリングによるものらしい)、という感じであった

そのため微妙にモデルが異なるため、最終的には人力でEnsembleを行い、最適な結果となるようパラメータ調整を行っていた

f:id:Radperia:20200827143940j:plain

結果

public LB: 890位からprivate LB:74位と816位ものshake upで何故か銀メダルを取れた

f:id:Radperia:20200827143349j:plain

これはコンペ中にも思っていたが、妙に投稿数が少ない割に同一のpublic scoreを持つ参加者が多かった

最終的には秘密裏に提出データを金銭でトレードしていたらしく大量のBANとオーバーフィットによる(多分)shake upが発生していた

複数モデルから最終的な結果を調整したのが功を奏したと思っている

ただ本当に何も分からないので、今回を機に色々と知見を深められればと思う

Pupil Labsを使用して、Unity上に目元の映像を抽出する方法

やりたいこと

f:id:Radperia:20200725170735p:plain

上記画像のように、HMDを装着した際でも目の位置が正しいかどうかを把握したい。

更に、目の位置が正しくてもconfidenceが良くない時もあるので、confidenceの値を見ながら調整できるようにしたい。

環境

  • Unity 2019.4.2f1
  • Pupil Capture v2.1.0
  • Hmd-Eyes.VR.v1.3

下準備

Edit > Project Settings > Player > Api Compatibility Level > .NET 4.x に変更
Assets > Import Package > Custom Package > Hmd-Eyes.VR をインポート

手順

  1. Assets > Plugins > Pupil > Demos > FramePublisherDemo を呼び出し
  2. Eye Frame Visualizer, Connection を使用したいScene内にコピペ

    f:id:Radperia:20200725170737p:plain f:id:Radperia:20200725170741p:plain

  3. コピペすると大体ここら辺の依存関係が崩れるから、適当に修正

  4. これだけで目周辺の位置を表示することが可能、楽。Demoに感謝。

    以下はconfidence値を取得して下部に出力する方法。

  5. GameObject > UI > Canvas を生成

  6. Canvas下に GameObject > UI > Text を生成
  7. Text に適当なC#ファイルをアタッチ

以下適当なソースコード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace PupilLabs.Expansion{
    public class ReceivePupilConfidence : MonoBehaviour{
        
        public SubscriptionController subsCtrl;
        public TimeSync timeSync;
        
        public Text statusText;
        private PupilListener listener;
        
        private Text confidenceText;
        private float timeleft;
        private bool flag;
        
        void Start(){
            this.confidenceText = this.GetComponent<Text>();
        }
        
        void OnEnable(){
            if(listener == null){
                listener = new PupilListener(subsCtrl);
            }
            listener.Enable();
            listener.OnReceivePupilData += ReceivePupilData;
        }
        
        void OnDisable(){
            listener.Disable();
            listener.OnReceivePupilData -= ReceivePupilData;
        }
        
        void Update(){
            flag = false;
            timeleft -= Time.deltaTime;
            if(timeleft <= 0.0f){
                timeleft = 3.0f; // 3s間隔でconfidence表示を更新
                flag = true;
            }
        }
        
        void ReceivePupilData(PupilData pupilData){
            double unityTime = timeSync.ConvertToUnityTime(pupilData.PupilTimestamp);
            Debug.Log($"Receive Pupil Data with method {pupilData.Method} and confidence {pupilData.Confidence} at {unityTime}");
            if(flag) this.confidenceText.text = pupilData.Confidence.ToString();
        }
    }
}

基本的にはPupilDataDemo.csを参考に書き換えていけば良い。

参考文献

pupil-labs Developer Documentation
https://github.com/pupil-labs/hmd-eyes/blob/master/docs/Developer.md

Qiita Unityでだいたい〇秒ごとに処理を行う https://qiita.com/okuhiiro/items/4c76fd8862e2bbb08ac7

Codeforces Round #605 Div.3 参加記録

大敗


研究が落ち着いたので半年近くぶりに競プロ、コンテストに復帰した。
結果は2完。1361->1329(-32)。酷い。

A - Three Friends


A. Three Friends
ただの全探索。20分もかかってるのは意味が分からない。

B - Snow Walking Robot


B. Snow Walking Robot
デバッグ用に残していた出力でWA。禿げあがりそう。
上下、左右の移動で多い方は少ない方に合わせる。
後はループが構築できるように調整して終わり。

C - Yet Another Broken Keyboard


C. Yet Another Broken Keyboard
なんでBより解けている人が多いのか全く分からない。
数学が全く分からないので、復習しようにも他人のコード読んでも分からない。分からない。

D以降


問題見てないです。

あとがき


明らかに弱すぎる。精進します。