高齢者施設向けレーダー転倒検知デモ『Vigil』の構築:360件の固定合成イベントセットで素朴なベースラインが再現率1.0・特異度0.167を記録した結果の可視化
機械学習ヘルスケアテクノロジーAI安全性

ミリ波レーダー転倒検知器の素朴なベースラインも同じ再現率1.0を達成した。だが一晩で7件の誤報を乱発した。

Ashutosh SinghalAshutosh Singhal2026年7月18日13 min

私がVigilのために構築した合成夜勤シフトにおいて、市販のベースライン検知器は02:00から06:00の間に9件のアラートを発報し、そのうち7件が誤報でした。ピーク速度5.0 m/sで検知されたシーリングファン。レーダー反射断面積(RCS)0.27のセラピードッグ。2.92 m/sで勢いよく椅子に腰掛けた入居者。その9件のアラートのうち2件が実際の転倒であり、そのうち1件は浴室での発生でした。その重心(セントロイド)の軌跡は、立位の1.53 mから1.07、0.84、0.625、0.344 mを経て下降し、床面レベルの0.119 mに落ち着き、呼吸は確認されるものの起き上がり動作はありませんでした。

そのシフトにおけるすべてのイベントは、固定シードから生成された、ラベル付きで物理法則に基づいた合成データであり、2つの検知器はいずれも私が作成したものです。だからこそ、都合の悪い事実も率直に語ることができます。あの市販ベースラインもまた、浴室での転倒を検知できていたのです。

Vigilは、高齢者施設においてレーダー特徴量ストリームとナースコールシステムの間に配置するために私が構築したインテリジェンス層です。施設が記録として残せるよう、すべての判定に理由を付記した上で、ALERT、SUPPRESS、またはROUTE TO HUMANを返します。デモのアクセス先はhttps://veriprajna.com/demos/smart-facility-fall-detectionです。私は転倒を検知することこそが難所だと想定して構築を開始しました。しかし初回の実行で、ベンチマークはその考えを否定しました。

再現率こそが、私が前面に押し出したかった指標でした

私は転倒検知の感度が主役になると期待してベンチマークを実行しました。そしてそれは実際に優れた数値です:ラベル付けされた360件のノイズを含む固定合成イベントセットにおいて、カスケードの再現率は1.0。しかしその隣の列こそが、自分が書こうとしていた記事の内容を一変させたものでした。素朴なベースラインはわずか2項の算術式であり、高速または低い位置の動きはすべて転倒とみなされます(peak_v > 2.0 OR min_cz < 0.45)。そして同一のデータセットにおいて、このベースラインもまた1.0の再現率を記録したのです。感度は転倒検知のマーケティングが拠って立つ領域ですが、両方の検知器がその最高値に張り付いています。

両者を分かつ差は、誰もスライドに載せない行に完全に現れています。交絡因子に対する特異度はカスケードが1.0、ベースラインが0.167であり、無害なイベントあたり0.833の誤報率となります。ベンチマークが想定する1部屋あたり1日30件の無害な動体トリガーにこれを当てはめると、ベースラインでは1部屋あたり1日25.0件の誤報が発生することになります。市販センサーについて公表されている既存の誤報範囲は1部屋あたり1日5〜15件であり、センサーの感度不足ではなくアラーム疲労こそが、これらの導入が失敗に終わる主因として記録されています。

技術系の読者に指摘される前に、自ら述べておくべき点があります。融合重み(data/fall_model.json)は、tools/fit_fall_classifier.pyによって、デモ自体のシナリオジェネレーター(360件のイベントセットを生成したのと同じジェネレーター)上で適合されたものです。これは私が示した2つの1.0という数値に対して誰しもが提起し得る最も強力な反論であり、そしてそれこそが、私が2つの1.0のどちらよりも0.167という数値を重視する理由でもあります。ベースラインの失敗は、私の訓練環境の産物(アーティファクト)ではありません。シーリングファンが存在する現実世界において、単純な閾値が必然的にもたらす結末なのです。

本物の転倒が発生したとき、誰かがまだ耳を傾けてくれているかどうかを決めるのは、あの7件の誤報なのです。

交絡因子は単一の特徴量を打ち破るように設計されていた

私の最初の直感は分類器を改良することでしたが、それは間違った直感でした。構築の初期段階では、これを単なる判別問題として扱い、「転倒と非転倒を分離する特徴量を見つけ出し、それに大きな重みを付けて次に進む」と考えていました。しかし、私がすでに作成していたシナリオジェネレーターは、意図的にそれを不可能にしていたのです。

各交絡因子は、次の目的で生成されています:何らかの個別特徴量において実際の転倒と重複すること。Cam 5での勢いよく座り込む動作は、転倒と同規模の2.92 m/sの速度バーストを伴い、0.46 mの高さに落ち着きます。Cam 10の浴室における同様の動作はピーク速度3.31 m/sに達し、0.44 mに落ち着きます。セラピードッグの動きやタオルを拾う前屈動作はいずれも重心を下げますが、これはベースラインのルールのもう一方の条件に該当します。私が記述し得たどんな単一テストも構造的に打破されており、これこそがベースラインが意図的に負けさせたダミー(わら人形)に騙されたのではなく、0.167という数値で真に欺かれた理由です。

速度は私が最も確信を持っていた特徴量でしたが、分類器に残ることはありませんでした。最終的に残ったのは、床面近接度、衝撃エネルギー、下降落差、レーダー反射断面積(RCS)プロキシという4つの特徴量に基づくロジスティックモデルであり、これらを統合してキャリブレーションされたP(fall)を算出します。速度の項はP(fall)に一切含まれていません。モジュールのdocstringには、速度を使うと考えていた頃の古い行がまだ残っています。これはプレーンなnumpyで書かれており、誰でもファイルclassifier.pyを開いてその全体を頭の中で把握できるほど小規模です。生命の安全に関わるシステムにおいて、その簡潔さはAUCのスコアをもう1ポイント上げることよりも私にとって価値があります。

私がCam 10の抑制(SUPPRESS)判定を最初に見せるのは、そのパネルが意見の相違の全貌をわずか1行で表しているからです。

VigilのCam 10(浴室)の詳細パネル。「速度バーストがあるが重心は座面の高さである0.44 mに落ち着き、床面ではなく、強い衝撃もない」という理由行とともにSUPPRESS(抑制)判定を表示。
Cam 10・Bathroomは浴室で勢いよく座り込む動作であり、ピーク速度は3.31 m/sに達します。Vigilは理由行に決定的な特徴量を記録した上でSUPPRESSを記録します。「重心は座面の高さである0.44 mに落ち着き、床面ではなく、強い衝撃もない」という内容です。この速度だけで、素朴なベースラインの `peak_v > 2.0` という条件を満たしてしまいます。

1つの8秒ウィンドウ、4つの条件

私は部外者として読むならこうあってほしいと思えるコードとして、時間的ナラティブ検証器を作成しました。temporal.py が要求するのは、同一の8秒間のウィンドウ内における4つの条件であり、その最初の5分の1で立位が確立されていること:重心の中央値が1.2 m超、ウィンドウ内のどこかで0.6 mを超える下降と1.8 m/sを超えるピーク速度を伴うこと、3フレーム移動平均が0.50を超える持続的な広帯域衝撃があること、そして重心が実際に0.30 m未満に到達することです。持続的衝撃テストが存在するのは、単一フレームのスパイクは安易に生じ得るのに対し、人体が床に衝突する現象はそうではないからです。

アプリが出力する理由文字列には「standing → descent → impact → floor」と表示され、これは看護スタッフが事故を把握する順序そのものですが、実際の実装では順序を強制するのではなく、ウィンドウ全体にわたってそれらの条件の論理積(AND)を取っています。これはステートマシンではなく、エンジニアがソースコードを見て「解説文では他に何が端折られているのだろう」と疑念を抱くくらいなら、私自身がその事実を率直に書いておきたいのです。

これらを満たして初めて、ゲートは0.20超の呼吸確認と、0.70以上の転倒信頼度を加えます。これら3つの値(床面レベル0.30 m、呼吸0.20、信頼度の下限0.70)は、どのモデルからも独立したプレーンなコードとして記述されています。重要なのはその順序です。モデルのスコアが参照される前に、決定論的条件が満たされていなければなりませんそのため、信頼度スコアだけでアラートが捏造されることは決してありません。より低いP(fall)によってALERTをSUPPRESSに変更することは可能であり、これは「沈黙することは許されても、捏造することは許されない」レイヤーにとって適切な非対称性です。文書化されたそのブロックの外側には、さらにもう一つの決定的な閾値が存在します。それは、p_fall >= 0.40 という、gate.py 内のハードコードされた閾値であり、モデルのスコアのみに基づいて複数人滞在イベントを目視確認へとルーティングすることができます。この閾値に言及するのは、そうしなければ「文書化された3つの閾値」という表現が実際以上の重みを持ってしまうからです。

抑制判定の記録こそが、州の監査で実際に求められる証跡である

私が製品らしいものを構築する前にまず判定台帳(Decision Ledger)を作ったのは、私が答えられなかった問いが「転倒を検知できたか」ではなく、「なぜ2時13分に203号室でアラートが発報されなかったのか」だったからです。そして誰かに問われた時点で、その答えはすでに書面記録として存在していなければなりません。そのシフトで発生した12件のイベントのうち10件は抑制(SUPPRESS)であり、それぞれに判定根拠となった特徴量の値が記録されています。Cam 6の非人体ターゲットでは人間の最小値0.55に対してレーダー反射断面積0.27、Cam 7とCam 12の前屈動作では閾値0.50に対して衝撃エネルギーが0.07であり、重心の下降は0.60 mおよび0.59 mで止まっていました。

Vigilのフロアビューと判定台帳(Decision Ledger)。Cam 12からCam 6までのSUPPRESS行が、それぞれの理由テキストとともに一覧表示されている。
シフト終了後の判定台帳。Cam 3・Bathroomのアクティブなインシデントが信頼度99%で表示されている。抑制された各行には決定理由が記載されている:Cam 10の座面高0.44 mへの静止、Cam 6の人間の下限を下回るレーダー反射断面積0.27、Cam 7およびCam 12の立位へと復帰した下降動作。
これら10件の抑制された行こそが監査官の尋ねる対象です。なぜなら、それらは何も起きなかったイベントであり、それでもなお誰かがその理由を説明しなければならないからです。

部屋ごとのキャリブレーションのうち、実際の判定に組み込まれているのは一部に過ぎません。Cam 1のシーリングファンが抑制されるのは、Room 214のクラッターマップにおいて (1.5, 1.5, 2.45 m) に固定位置のドップラーエントリが登録されており、check_clutter がそのボクセルでそれをマスクするからです。その実行パスは本物です。一方、rooms.json に記載されている部屋ごとの座面やベッドの高さ(Room 118浴室の0.42 mやRoom 203の0.45 m)、およびその横の手すりエントリは、V1のどのコードパスも読み取っていない キャリブレーションデータです。私が勢いよく座り込む動作の判定に使用している座面高さの帯域は、0.38〜0.60 mという単一のグローバルなテストです。そのファイルには、何にも使用されていない long_lie_sec: 180.0 というキーすら存在します。部屋ごとのキャリブレーションは実際の現場導入で費用を支払って行う統合作業であり、今回のビルドで判定に接続されているのはドップラーマスクのみです。

エクスポート機能は、すべてのアラート、回送、抑制について決定要因となった特徴量とポリシー上の理由を網羅したシフト監査JSONを出力し、これはCMS F689やQAPI(品質保証・性能改善)の記録バインダーが求めるものです。臨床インシデント記録は、その構造化された証拠から別途作成され、JSONの内部ではなくインシデントパネルに表示されます。

発報を許可したアラートと、断定を許さなかった転倒

私は意図的に、そのシフトのクライマックスを浴室に設定しました。浴室は最もリスクが高い部屋であり、カメラが選択肢になり得ない唯一の場所です。米国の19の州では老人ホームの居室へのカメラ設置を規制する法律が制定されており、同意があれば居室への設置は概ね認められているものの、浴室はプライバシーの観点から実質的に除外されています。レーダーの特徴量には画像情報が含まれません。だからこそ、カメラが立ち入れない場所に導入できるのです。

Cam 3がそのイベントであり、VigilはALERT、カテゴリ long_lie、信頼度0.99、床面時間4.8秒 を返し、エスカレーションラダーは即時CNA(認定看護助手)、90秒で責任看護師、180秒で看護部長(DON)へと設定されます。ナースコールのバッジテキストには「Room 118B Bathroom: Fall Detected, 99% confidence. Resident on floor 5s. Breathing confirmed.」と表示されます。ディスパッチはレガシーなRauland無電圧接点信号とAscom/AustcoのMQTT/RESTペイロードの両方を出力し、いずれもログ記録されるアダプタースタブを経由します。これらには実際のナースコール機器は接続されていません。それでもなお構築する価値がある理由は「ロングライ(長時間放置)」にあります。床の上に1時間以上倒れたままの高齢者の半数は、6か月以内に亡くなっています。

VigilのCam 3(浴室)のインシデント詳細:118B号室のナースコールバッジ、エスカレーションラダー、信頼度0.99のペイロード、および臨床インシデント記録。
Cam 3・Bathroomのアラート詳細を展開した画面(バッジ、ペイロード、記録内の表示はRoom 118B)。ディスパッチペイロードには信頼度0.99、floor_time_sec 4.8、breathing true、long_lie_risk trueが記録され、その横にはCNA、責任看護師、DONへのラダーが表示され、その構造化された証拠からインシデント記録が作成されています。

そのパネルの中で、私が誇大に宣伝することを拒む数値が1つあります。衝撃からアラートまでの7.0秒という時間は、gate.py 内でホールドタイマーに3秒(定数)を加算して算出されたものです。アプリにはそれが表示され、私もその表示を引用しますが、これは測定されたシステム速度ではなく単なる算術計算であり、これをベンチマークされたレイテンシと呼ぶのは、その隣にある重大な真実の重みを損なうような些細な不誠実さにあたるでしょう。

私がより誇りに思っているのは、Vigilがアラートの発令を控えたイベントです。Cam 2はグラウンドトゥルース(正解データ)では実際の転倒であり、P(fall)は0.99に達していますが、それでもVigilは転倒と断定しません。室内には2つのターゲットが存在し、単身追跡はV1の対象範囲外であるため、ゲートは低い信頼度でのROUTE TO HUMAN(人手による確認へ回送)を返します。素朴なベースラインは自動発報し、自らが実力で検知したわけでもない手柄を横取りします。そのシフトでは2件の実際の転倒が発生しました。Vigilはそのうち1件でアラートを発報し、もう1件をスタッフによる確認へと回送しました。私はこれを「すべての転倒を検知した」などと表現するつもりはありません。実際にはそうではないからです。ベンチマーク全体を通じて、複数人滞在時の転倒40件中40件すべてが人手による確認へルーティングされ、過剰な誤報も検知漏れもゼロでした。

スコアボードが主張することを許されている範囲

「Shift Results(シフト結果)」モーダルの下にある注記事項の行は、そのパネルの中で私が最初にドラフトした部分です。このモーダルは、今回のシフトにおいて既存検知器の7件に対して本エンジンが0件の誤報であったこと、2件の実際の転倒のうち1件を検知し1件を人手による確認へ回送したこと、ラベル付き360件のイベントに対して交絡因子の特異度が100%であったこと、そして1部屋あたり1日25件と予測される誤報に対して0.0件であったことを報告しています。

02:00から06:00の夜勤シフトに関するVigilの「Shift Results」モーダル:1部屋あたり1日25件の誤報に対して0.0件、実際の転倒2件中1件を検知、1件を人手による確認へ回送、ラベル付き360件のイベントにわたる交絡因子特異度100%。
「Shift Results」スコアボード。既存検知器の1部屋あたり1日25件に対して本エンジンは0.0件の誤報であり、実際の転倒2件のうち1件でアラートを発報、1件を目視確認へと回送。フッターには適用範囲が明記されています:360件のラベル付きノイズ含有イベント、合成レーダー特徴量ストリーム、実稼働センサーなし、PHI(保護対象保健情報)なし、カメラなし。

これらの数値は、固定された合成ゴールデンセットを記述したものであり、それ以上のものではありません。本番環境での精度でも、臨床結果でも、検証済みの医学的主張でもなく、施設に対する保証などでは決してありません。実際のパイロット運用では、シャドウモードでのキャリブレーションを経て1部屋あたり1日2件未満の誤報を目標とします。そしてそれこそが、私が看護部長(DON)の前に提示する数値です。なぜなら、その数値に対してなら責任を負うことができるからです。0.0という数値は、私が皆様にお渡しできるデータセット上で、本メカニズムが転倒と交絡因子を分離できている証拠に過ぎず、一度も足を踏み入れたことのない建物に対する約束ではないのです。

私が今、生命の安全に関わるアラートに求めている基準

この構築を経て、私は転倒検知が何に優れていなければならないのかについて、はるかに厳格な定義にたどり着きました。検知自体は閾値に過ぎず、私自身のテストセット上でも単純な閾値がすでに再現率1.0を記録しています。看護スタッフの信頼を勝ち取る仕事とは、「拒否(refusal)」することです。ファンがどのボクセルを占有しているかを把握するクラッターマップ、単一フレームの衝撃を認めない衝撃テスト、勢いよく座り込む動作と転倒を区別する床面到達条件、そしてモデルではなく州の監査官が「なぜシステムがその動作を行ったのか」を読み取れるように記述されたゲートこそがそれなのです。

詳細なウォークスルーはhttps://veriprajna.com/demos/smart-facility-fall-detection に掲載されており、台帳にある10件の抑制(SUPPRESS)行こそが、そのシフトの成否が実際に決せられた場所なのです。

文章での説明を読むよりもシフトの様子を実際に見たいという方のために、夜勤全体の実行風景を最初から最後までご覧いただけるデモを用意しました。

シーリングファンでアラートを鳴らすようなシステムは1週間もしないうちにミュートされ、ミュートされたシステムは何ひとつ検知できなくなります。私がこのインテリジェンス層に与えることができた最も洗練された振る舞いは、決定要因となった数値を付記した上で、記録に残る形でアラートを「拒否」する能力でした。Cam 2においてその数値は0.99でしたが、それでもなお正しい判断は、そのイベントを人手による確認に委ねることだったのです。

関連リサーチ

他のプラットフォームでも公開

確かな信頼のもとに、AIを構築する。

次世代のエンタープライズAI構築において豊富な経験を持つチームと、ぜひご一緒ください。信頼できるAI戦略の設計・構築・導入を、私たちがお手伝いします。

Veriprajna ディープテック・コンサルティング は、ヘルスケア・金融・規制対応分野における安全性重視のAIシステム構築を専門としています。当社のアーキテクチャは確立されたプロトコルに照らして検証され、包括的なコンプライアンス文書を備えています。