※本記事は、CJ Chung氏によるAI for Goodワークショップ「MathDance: Hands-on workshop to learn Math, Coding, and AI」の内容を基に作成されています。ワークショップの動画は https://www.youtube.com/watch?v=86cVxk_Sw9I でご覧いただけます。本記事では、ワークショップの内容を要約しております。なお、本記事の内容は登壇者の見解を正確に反映するよう努めていますが、要約や解釈による誤りがある可能性もありますので、正確な情報や文脈についてはオリジナルの動画をご視聴いただくことをお勧めいたします。
登壇者のCJ Chung氏は、Lawrence Technological UniversityのコンピュータサイエンスProfessorおよびCS & AI Robotics(CAR)LabのDirectorを務めています。
本ワークショップはAI for Good グローバルサミットの一環として開催されました。AI for Goodは、健康・気候・ジェンダー・包括的繁栄・持続可能なインフラをはじめとするグローバルな開発課題の解決にAIを活用することを推進する、国連の主要なアクション志向プラットフォームです。国連の情報通信技術専門機関である国際電気通信連合(ITU)が40の国連関連機関と連携し、スイス政府との共催で運営しています。
1. ワークショップの概要・目標・登壇者紹介
1.1 学習目標とDay 2の位置づけ
CJ Chong: 皆さん、AI for Good グローバルサミット Day 2 のMathDanceワークショップへようこそ。私はアメリカ・ミシガン州サウスフィールドにあるLawrence Technological UniversityでコンピュータサイエンスのProfessorを務めているCJ Chongと申します。自律ロボット競技大会「Robo Fest」の創設者であり、コネクテッド・自動走行車両の研究を行う「Car Lab」のディレクターでもあります。本日は皆さんとともに、数学・AI・プログラミングを融合させたユニークなワークショップを進めていきます。
今日のワークショップには、複数の学習目標があります。まず機械学習および深層学習の基本的な概念を理解すること、次にScratchプログラミングのスキルを習熟・強化すること、そして数学的基礎と数式についての理解を深めることです。さらにこれら三つの要素、つまり数学・AI・Scratchコーディングを統合して、実際に動くMathDanceゲームアプリを開発することが本ワークショップの核心的な目標です。Day 2の特徴として、Day 1のプロジェクトをベースにしながら、新たに音楽要素を加えた点が挙げられます。最終的には、国連の持続可能な開発目標(SDGs)の一つである「質の高い教育」の推進にも貢献したいと考えています。
本ワークショップはDay 1の内容を踏まえた続編ですが、Day 2単独でも学習が成立するよう設計されています。今日のセッションではDay 1でカバーした内容のほぼすべてを改めて扱いますので、初めて参加する方もご安心ください。スライドのPDFはRobo Festのウェブサイトおよびニューラルネットワークのリソースページからダウンロードできます。学習の効率を高めるため、可能であれば追加モニターにPDFを表示しながらワークショップに参加することを強くお勧めします。
1.2 登壇者・アシスタントの紹介とDay 2デモの概要
CJ Chong: 本日のワークショップには、私を支えてくれる三名のアシスタントがいます。プレゼンテーションのレビューや、チャット欄への技術的な質問への回答を担当してくれていますので、何か詰まったことがあればぜひチャット機能を使って質問してください。まずDr. Guang Chun Zhouに自己紹介をお願いします。
Guang Chun Zhou: 皆さん、こんにちは。私はMichiganのLawrence Technological Universityで数学のProfessorをしているGuang Chun Zhouです。よろしくお願いします。
CJ Chong: ありがとうございます。次にJuliusをご紹介します。
Julius Caesar: こんにちは、Julius Cesarです。私はLawrence Technological Universityのデュアルエンロールメント学生で、Robofest競技にも参加しています。また、Dr. Chongのもとで夏期研究にも取り組みました。どうぞよろしくお願いします。
CJ Chong: ありがとう、Julius。次にGregoryをご紹介します。
Gregory Aaron: はじめまして、Gregory Aaronです。アメリカの高校生で、Lawrence Technological UniversityでDr. Chongと研究を行いました。よろしくお願いします。
CJ Chong: ありがとうございます、Gregory。繰り返しになりますが、技術的な質問はぜひチャット機能でお寄せください。アシスタントたちが丁寧に対応します。また、画面はフルスクリーン表示での受講をお勧めします。
さて、今日のDay 2プロジェクトがどのようなものか、まず動画でご確認いただきましょう。動画の中では、学習済みのMLモデルが準備完了し、各問いに対して5秒の制限時間が与えられます。「show me y = x」「show me y = −x」「show me y = 10x」「show me y = 0」といった指示に従って正しい手のポーズを取ると「good job」と読み上げられ、全問正解すると正答率と所要時間が発表されたうえで、ダンス音楽が流れて「Let's Dance」と締めくくられます。このデモでは全8問を35秒で完答し、正答率100%を達成しています。ちなみに私の個人記録は34秒です。このようなゲームアプリを本日のワークショップで皆さん自身の手で作り上げていただきます。
2. 機械学習・深層学習の概念と本ワークショップでの活用全体像
2.1 AI・機械学習・深層学習の定義と関係
CJ Chong: まず機械学習と深層学習の基本概念を整理しておきましょう。AIとは人間の知性を模倣しようとする技術の総称です。その中の一分野である機械学習は、機械(モデル)がサンプルデータから学習する仕組みを指します。サンプルデータにはラベル付きデータ、ラベルなしデータ、過去の経験データといった種類がありますが、本ワークショップではラベル付きデータのみを使う「教師あり学習」の手法を採用します。さらに深層学習とは、機械学習の特殊なケースであり、脳の神経回路に着想を得たアルゴリズム、すなわちニューラルネットワークを用いてサンプルデータから学習するものです。本日も引き続き、ラベル付きデータを用いた教師あり学習で深層学習モデルを訓練します。
2.2 5クラス分類モデルの設計とポーズ・方程式の対応関係
CJ Chong: 本ワークショップのアプリは、皆さんの手のポーズをウェブカメラで撮影し、それがどの数式に対応するかを深層学習モデルが判定するという仕組みです。具体的には次の5クラスを設定します。y=0は両腕を水平に広げるポーズ、y=xは右斜め上に向けるポーズ、y=−xは左斜め上に向けるポーズ、y=10xは両腕をほぼ垂直に立てるポーズ、そしてnoneは手を見せない場合のデフォルトクラスです。各クラスにつき約50枚のサンプル画像を収集し、この5クラスの画像を用いて深層学習モデルを訓練します。
ここで一つ実践的なアドバイスがあります。サンプル数が少ない場合、袖をまくっておくとモデルの認識精度が上がります。腕の輪郭が明確に映るほうがモデルにとって識別しやすくなるためです。ぜひ試してみてください。
2.3 Teachable Machine・ml4k・Scratchの連携フロー
CJ Chong: 本ワークショップでは三つのツールを組み合わせて使います。まずGoogle Teachable Machineです。これはGoogleが提供するブラウザベースの機械学習ツールで、内部ではMobileNetと呼ばれる事前学習済みのニューラルネットワークを活用しています。ここでサンプル画像の収集・モデルの訓練・クラウドへのエクスポートまでを行います。次にMachine Learning for Kids(ml4k)サイトです。MITの標準Scratchサイトではなく、このml4kサイトを使う点が重要です。ここからScratchを起動することで、機械学習モデルとの連携に必要な専用ブロックが利用できるようになります。三つ目がScratchそのものです。Scratchのコードが、ウェブカメラの映像をモデルに送信し、モデルからラベルと信頼度(confidence)を受け取り、ゲームのロジックを実行します。
全体の流れを整理すると次のようになります。まず5クラス分の画像をTeachable Machineで収集し、深層学習モデルを訓練します。訓練が完了したらモデルをクラウドにエクスポートし、共有URLを取得します。次にml4kサイトからそのURLを使ってScratchを開き、モデルとの接続を確立します。アプリの動作中は、Scratchがウェブカメラでキャプチャしたリアルタイムの画像をモデルに送信します。モデルは受け取った画像を解析し、その画像が5クラスのどれに属するかというラベルと、その判定への信頼度をScratchに返します。この「未知の画像に対してモデルが答えを返す」ステップを「推論(inference)」と呼びます。Scratchはその推論結果をもとにゲームの進行を制御します。これが本日のアプリ全体の動作原理です。両サイトは頻繁にアクセスすることになりますので、ブックマークしておくことを強くお勧めします。
3. Scratchプログラミングの基礎概念(Day 2向け新要素)
3.1 論理OR演算子の使い方
CJ Chong: Day 1では論理AND演算子を使ったプログラムを作成しましたが、Day 2では新たに論理OR演算子を導入します。具体的なコード例で確認しましょう。緑の旗がクリックされたとき、まず「recognized」という変数に「C」をセットし、「certainty」という変数に45をセットします。ここでOR演算子を使った条件分岐を作ります。「recognizedがCと等しい」または「certaintyが50より大きい」のどちらか一方でも真であれば、moon(月)の音を鳴らすというコードです。この例では、certaintyは45なので「certaintyが50より大きい」という条件は偽です。しかし「recognizedがCと等しい」という条件は真ですので、OR演算子によってどちらか一方が真であれば全体が真となり、結果としてmoonの音が鳴ります。AND演算子は両方の条件が同時に真でなければならないのに対し、OR演算子はどちらか一方が真であれば十分という点が大きな違いです。このOR演算子は、今日のゲームアプリの核心部分であるカウントダウンスクリプトの終了条件を記述する際に欠かせない道具となります。
3.2 タイマーの導入と100万回ループ実験による体感的理解
CJ Chong: 次に、Day 2で新たに使うタイマーの概念を紹介します。Scratchには「timer」という特殊な変数があり、リセット後からの経過時間を自動的に追跡し続けます。このタイマーをリセットしてから、後で再びtimerの値を読み取ることで、ある処理にかかった時間を計測することができます。今日のゲームアプリでは、全問に要した合計時間を計測してプレイヤーに伝えるためにこのタイマーを使います。
タイマーの感覚を身につけるために、タスク1として次の実験を試してください。緑の旗がクリックされたとき、まずcounterという変数を0にセットしてタイマーをリセットします。次に「100万回繰り返す」ループを作り、ループの中でcounterを1ずつ増やします。ループが完了したら、text to speechのspeakブロックを使って、かかった時間と最終的なcounterの値を読み上げさせます。時間の読み上げにはjoinブロックを活用します。joinブロックは二つの値を結合して一つの文字列として返すブロックで、今日は非常に多用します。例えばtimerの値と「seconds taken」という文字列をjoinでつなぐことで、「0.7 seconds taken」のように読み上げさせることができます。
私が実際にこのコードを実行したところ、1回目は0.694秒、2回目は0.727秒という結果が出ました。つまり私のコンピュータでは、100万回の繰り返し処理がおよそ0.7秒で完了するということです。Scratchが1秒間に約140万回の単純な加算処理をこなせるという事実は、タイマーを使った時間計測がゲームアプリの中でいかに有効かを体感させてくれます。なお、Scratchが100万という数値を読み上げる際に「1e6」のような指数表記になることがありますが、これは正常な動作です。ぜひ皆さんも実際に試してみてください。
3.3 ブロードキャストと並列スクリプトの実験・デバッグ体験
CJ Chong: Day 2でもう一つ重要な新概念が、ブロードキャストを使ったスクリプトの並列実行です。これはコンピュータサイエンスの重要な概念で、二つのスクリプトが互いに独立しながら同時に動作するというものです。タスク2として次のコードを試してください。まずcounterを3にセットします。次に「countdown」というブロードキャストメッセージを送信します。このブロードキャストが、別の独立したスクリプトを起動するトリガーになります。起動された側のスクリプトは「countdown」メッセージを受信すると、「meow」の音を鳴らしてからcounterを1減らす処理を3回繰り返します。つまりこのスクリプトが完了するとcounterは0になります。一方、ブロードキャストを送信した側のスクリプトは、「repeat until(空ボディ)」というブロックを使って「counterが1未満になるまで何もせず待ち続ける」という処理を行います。counterが0になった瞬間に終了条件が満たされ、ループを抜けて「hello」と発話します。
このコードを実際に動かすと、meow音が3回鳴り、その直後にhelloと読み上げられる動作を確認できます。並列実行の仕組みによって、カウントダウンしている側のスクリプトと、終了を監視している側のスクリプトが同時に動いているわけです。
ただし、私が実際にコードを組んだ際にバグが発生しました。最初、counterの初期値を3ではなく誤って0にセットしてしまったため、ブロードキャストが送られた時点でcounterがすでに0であり、「counterが1未満」という終了条件が即座に満たされて「hello」が鳴ってしまいました。meow音が一度も鳴らずにhelloだけが聞こえるという挙動を見て初めて誤りに気づき、初期値を3に修正することで正しく動作しました。このデバッグ体験は、変数の初期化が並列スクリプトの動作に直接影響するという重要な気づきを与えてくれます。
このブロードキャストと並列スクリプトの仕組みは、今日のゲームアプリで「各問いに5秒の制限時間を設ける」という機能を実現するための核心的な技術です。ユーザーが正しいポーズを取るまで推論を繰り返すスクリプトと、5秒をカウントダウンするスクリプトを並列に走らせることで、どちらかの条件が満たされた時点でゲームが次のステップに進む、という動作が実現できます。ぜひ実際にコードを組んで、並列実行の感覚を体で覚えてください。
4. Google Teachable Machineによるモデルの学習とエクスポート
4.1 サンプル画像の収集・品質チェック・再学習による精度改善の実験
CJ Chong: それではいよいよGoogle Teachable Machineを使って深層学習モデルを訓練していきましょう。まずブラウザでTeachable Machineのサイトにアクセスし、「Get Started」ボタンをクリックします。画像・音声・ポーズの三種類のプロジェクトが選べますが、今日は「Image Project」を選んでください。さらに「Standard Image Model」を選択すると、クラスを登録するウィンドウが表示されます。
サンプルの収集手順を説明します。最初のクラスはy=0です。クラス名を「0」と入力し、「Webcam」ボタンをクリックしてカメラを起動します。y=0のポーズ、つまり両腕を水平に広げた状態で「Hold to Record」ボタンを押し続け、約50枚の画像を収集します。このとき、カメラに近い距離と遠い距離を交互に変えながら撮影することで、モデルの汎化性能が高まります。同様の手順でy=x、y=−x、y=10xの各クラスを収集します。y=−xは「minus x」と呼ぶことをお勧めします。最後にnoneクラスとして、手を見せない状態の画像を約50枚収集します。
ここで一点注意があります。ブラウザを起動してもウェブカメラの映像が表示されないことがあります。そのような場合は焦らずブラウザを完全に終了し、再起動してから再度サイトにアクセスしてください。私自身もライブデモ中にこの問題が発生し、ブラウザを再起動することで解決しました。
収集が終わったら、必ず全クラスの全画像を目視で確認してください。不要な画像や誤ったポーズが混入していた場合は削除します。この品質チェックのステップを省略すると、モデルの精度に直接悪影響を及ぼしますので手を抜かないようにしましょう。
4.2 モデルの学習・テスト・クラウドエクスポートとScratchへの接続確認
CJ Chong: サンプル画像の収集と品質チェックが完了したら、「Train Model」ボタンをクリックしてモデルの訓練を開始します。Google Teachable Machineは内部でMobileNetという事前学習済みネットワークを活用しているため、今回収集した5クラス分のデータに対してファインチューニングが行われます。訓練にかかる時間はおよそ20秒程度で、完了すると「Ready」と表示されます。
訓練が終わったらすぐにテストを行いましょう。私が実際にテストしたところ、noneのポーズでは信頼度100%、y=0・y=−x・y=10xでも非常に高い信頼度が得られました。しかしy=xクラスの認識精度がやや不十分に感じられたため、このクラスのサンプルをいくつか追加して再訓練を行いました。再訓練後に同じポーズでテストすると、認識精度がわずかに向上したことを確認できました。このように少数のサンプルを追加するだけでも改善効果が得られるという点は、実際に手を動かして体感することが重要です。満足のいく精度が得られるまでサンプルの追加と再訓練を繰り返し、すべてのクラスを高精度かつ安定して識別できるモデルを仕上げてください。
十分な精度が確認できたら、モデルをクラウドにエクスポートします。「Export Model」ボタンをクリックし、オプションは何も変更せずそのまま「Upload my model」をクリックします。数秒から数十秒でアップロードが完了し、共有用のURLが表示されます。このURLをコピーしたら、必ずメモ帳などのテキストファイルに貼り付けて保存してください。URLを紛失すると再エクスポートが必要になります。私は自分でメモ帳を開き、URLとともに「5つの数式クラス・撮影日2024年9月25日・自宅で撮影」といった情報を一緒に記録しておきました。こうしておくと後日モデルを再利用する際に非常に便利です。
URLの保存が完了したら、Teachable Machineのカメラを閉じてください。ウェブカメラが引き続きTeachable Machine側で使用中になっていると、次のステップでScratchがカメラにアクセスできなくなります。必ずカメラを解放してからブラウザのタブを閉じるか、Teachable Machineから離れるようにしてください。またこのタイミングで、プロジェクトファイルを「.TM」形式でローカルに保存しておくことも強く推奨します。私は「MathDance_Day2.TM」というファイル名でダウンロードフォルダに保存しました。再度訓練をやり直す手間が省けますし、後日同じモデルを別のプロジェクトで使い回すことも可能になります。
次にml4kサイトに移動します。ページを下にスクロールすると「Open a TensorFlow model」というリンクが見つかりますので、クリックするとダイアログが表示されます。先ほどメモ帳に保存したURLをここに貼り付け、モデルの種類が「Image」になっていることを確認してから「Open Scratch」をクリックします。Scratchが起動したら、画面左側にある「TM my image model」ブロックを探してクリックし、5つのクラス(0・x・−x・10x・none)が正しく読み込まれていることを確認してください。この確認を怠ると、後のコーディングで意図しない動作が発生することがあります。
接続確認用のシンプルなテストコードとして、緑の旗がクリックされたときに「wait until machine learning model is connected」ブロックで接続完了を待ち、接続が確認されたら「model connected」と発話するコードを作成してください。実行してみて「model connected」という音声が聞こえれば、ScratchとTeachable Machineのモデルが正しくつながっています。このコードはここで一度保存しておきましょう。プロジェクト名を「MathDance2」などわかりやすい名前に変更し、「Save to your computer」でローカルに保存してください。この接続確認済みのファイルがDay 2のアプリ開発の出発点になります。
5. MathDanceゲームアプリの開発(プロフェッショナル版)
5.1 新機能の仕様・変数設計・カスタムブロック構成
CJ Chong: ここからいよいよDay 2のメインであるMathDanceゲームアプリ、プロフェッショナル版の開発に入ります。まず今日実装する新機能を整理しておきましょう。
一つ目は5秒タイムアウト機能です。各問いに対してユーザーが5秒以内に正しいポーズを取れなかった場合、「time out」と読み上げて次の問いに進みます。二つ目は所要時間の計測です。全問を完答するまでにかかった秒数をタイマーで計測し、終了時に読み上げます。三つ目は正答率の計算と発表です。例えば8問中6問正解であれば「75% success」と読み上げます。四つ目はダンス音楽の再生です。全問正解(100%)を達成した場合にのみ、ダンス音楽を再生して「Let's Dance」で締めくくります。
これらの機能を実現するために、今日は多くの変数を新たに導入します。まずlabelは、モデルが推論した結果のクラス名を格納する変数です。confはその推論の信頼度(confidence)を格納します。Iはmath listからランダムに問いを選ぶためのインデックス変数です。Target equationは今回の問いとしてランダムに選ばれた方程式名を格納します。Target recognizedはユーザーが正しいポーズを取れたかどうかを管理するフラグ変数で、「yes」または「no」のいずれかをとります。seconds leftは残り秒数をカウントダウンするための変数で、初期値は5です。success counterは正解した問いの数を累積するカウンターです。number of questionsはゲーム全体の問い数を保持します。さらにmath listというリストを作成し、方程式名(0・x・−x・10x)を格納しておきます。
プログラムの構造についても説明します。今日のコードは、メインスクリプトと四つのカスタムブロック(my blocks)、そして一つのブロードキャストで起動される並列スクリプトという構成になっています。カスタムブロックの名前はそれぞれinitialize、pick one equation and ask、inference and check、Game endingです。コードが長くなるほどメインスクリプトをシンプルに保つことが重要ですので、処理の塊をカスタムブロックとして切り出す設計にしています。デバッグや動作確認の際には問い数を減らして検証し、最終的に本番の問い数に切り替えるという流れで開発を進めます。
5.2 initializeブロックとpick one equation and askブロックの実装
CJ Chong: まずinitializeカスタムブロックを作成します。「My Blocks」から「Make a Block」をクリックし、ブロック名を「initialize」とします。
initializeブロックの中身は次の通りです。最初にVideo Sensing拡張機能を使ってウェブカメラ映像をオンにし、透明度を0に設定します。これによりウェブカメラのクリアな映像が取得できるようになります。次にmath listを作成し、内容をいったんすべて削除してからクラス名を順番に追加していきます。追加するのは「0」「x」「−x」「10x」の四つです。続いてnumber of questionsを設定します。math listの長さに係数を掛けた値をnumber of questionsにセットします。デバッグ・テスト中は係数を1にして4問構成にしておき、開発が完了したら係数を2に変更して8問構成に切り替えます。次にsuccess counterを0に初期化します。そしてモデルとの接続を待機するブロック「wait until machine learning model is connected」を置き、接続が確立されたら「model connected、you have 5 seconds for each question」とtext to speechで読み上げます。最後にreset timerを置いて所要時間の計測を開始します。このタイマーリセットはinitializeの最後に置くことが重要で、モデルへの接続待機時間を計測対象から除外するためです。
次にpick one equation and askカスタムブロックを作成します。このブロックの役割は、math listからランダムに一つの方程式を選んでユーザーに問いかけることです。まず1からmath listの長さまでの範囲でランダムな整数を生成し、インデックス変数Iにセットします。次にmath listのI番目の要素をTarget equationに格納します。そして「show me y =」とTarget equationをjoinで結合して読み上げます。実際に4問版でテストしたところ、「show me y = x」「show me y = 0」「show me y = 10x」「show me y = −x」とランダムに出題される動作を確認しました。この時点でinitializationと問い生成の部分が正しく機能していることが確認できました。
5.3 inference and checkブロックと並列カウントダウンスクリプトの実装
CJ Chong: 次にinference and checkカスタムブロックを作成します。このブロックは、ユーザーのウェブカメラ映像をモデルに送って推論を行い、正しいポーズが認識されたかどうかを判定する処理を担います。
まずlabelをnull、confを0、Target recognizedをnoにそれぞれ初期化します。次に推論処理として、「TM my image model」の「label」レポートブロックを使ってウェブカメラ画像をモデルに送り、返ってきたクラス名をlabel変数に格納します。同様に「confidence」レポートブロックで信頼度を取得し、conf変数に格納します。続いて判定処理として、labelがTarget equationと等しい、かつconfが75より大きい、という二つの条件をAND演算子でつなぎ、両方が真の場合にTarget recognizedをyesにセットします。信頼度に閾値(75%)を設けている理由は、偶発的な誤認識を排除するためです。信頼度が低い場合は認識が不確かであるとみなし、正解とは判定しません。
このinference and checkブロックを単体でテストした結果、「show me y = 10x」「show me y = −x」「show me y = 0」の各問いに対して「good job」と正しく読み上げられることを確認しました。
次に並列カウントダウンスクリプトを実装します。pick one equation and askを呼び出した直後、inference and checkを呼び出す前に「start count five」というブロードキャストメッセージを送信します。このブロードキャストが、カウントダウンを担う並列スクリプトを起動します。
並列スクリプトの中身は次の通りです。「when I receive start count five」ブロックで起動し、まずseconds leftを5にセットします。次に「repeat until(Target recognized = yes OR seconds left = 0)」というOR条件のループに入ります。ループの内部では、wait 1 secondで1秒待機し、pop音を再生し、seconds leftを−1ずつ減算します。この処理によって、ユーザーが正しいポーズを取るか、あるいは5秒が経過するかのどちらかが起きるまで、1秒ごとにpop音を鳴らしながらカウントダウンが続きます。
一方のinference and checkブロック側も、「repeat until Target recognized = yes」のループで繰り返し推論を行い続けます。この二つのスクリプトが並列に動作することで、「5秒以内に正しいポーズを取れば正解、取れなければタイムアウト」というゲームの核心的な動作が実現されます。
5.4 Game endingブロックの実装・デバッグ・最終動作確認
CJ Chong: いよいよ最後のカスタムブロックであるGame endingを実装します。このブロックには三つの主要な処理があります。
まず正答率の計算と読み上げです。success counterに100を掛けてnumber of questionsで割ることで正答率を算出し、「○○% success」とjoinで結合して読み上げます。次に100%正解の場合のみ所要時間を読み上げる処理です。「success counter = number of questions」という条件をif文で判定し、真の場合にtimerの値と「seconds taken」をjoinで結合して読み上げます。三つ目はダンス音楽の再生です。100%正解の条件が満たされた場合、ダンス音楽を再生してお祝いします。最後にstop allを実行してすべてのスクリプトを停止します。stop allを置かないと、カウントダウンの並列スクリプトなどが動き続けてしまうため必須の処理です。
ここでデバッグ中に発生したバグを共有します。Game endingブロックを定義したにもかかわらず、メインスクリプトからの呼び出しを忘れてしまったため、ゲームが終了しても正答率が読み上げられないという問題が発生しました。ブロックを定義するだけでは動作せず、必ずメインスクリプトから呼び出す必要があります。このような「定義はしたが使っていない」というミスはよくあるバグのパターンですので、コードを書き終えたら必ず一通り確認してください。
修正後に4問版でテストを行ったところ、「100% success、18.059 seconds taken、Let's Dance」という動作を確認しました。続いて係数を2に変更した8問版で最終テストを実施し、「100% success、31.559 seconds taken、Let's Dance」というフルバージョンの動作を確認しました。ちなみに私の個人記録は34秒で8問を完答したものです。
動作確認が取れたら、デバッグ用に画面表示していた変数を非表示にしましょう。confidenceやnumber of questionsなどの数値はデバッグ中には便利ですが、ゲームのプレイ画面には不要です。最終的に画面上に残す変数は必要最小限にとどめることで、プレイヤーにとって見やすいクリーンなゲーム画面に仕上がります。ここまで完成したら必ずファイルをコンピュータに保存してください。
6. 音楽との同期・過去の実践事例・教育効果
6.1 外部音楽ファイルのテンポ解析と音楽・ポーズ表示の同期プログラム
CJ Chong: ゲームアプリが完成したら、次は音楽との同期という新しい要素に取り組みます。Scratchにはデフォルトでいくつかのダンス音楽が用意されており、サウンドタブから「dance」と検索すると複数の候補が表示されます。私のお気に入りは二番目に表示されるものですが、今日はそれに加えて外部からダウンロードしたpy_dance.wavというファイルも使います。このファイルは私のスライドPDFのリンクからダウンロードできます。取り込む手順はサウンドタブの「Upload Sound」からダウンロードフォルダ内のpy_dance.wavを選択するだけです。
音楽とポーズ表示を同期させるためには、まず音楽ファイルの構造を分析する必要があります。py_dance音楽ファイルは4小節構成で、1小節あたり1.5秒かかります。これをテンポに換算すると、1拍あたり0.375秒、すなわち1分あたり約126.32拍(♩=126 BPM)という計算になります。この楽譜表記では一定の音符が1分間に何回繰り返されるかを示しており、その値が126.32であることがテンポ設定の根拠になります。Scratchでテンポを設定する際はこの値を使ってください。
同期プログラムの構造を説明します。まずPreludeという関数を定義し、コスチュームをいったん最後のものに切り替えておきます。これはnext costumeブロックで最初のコスチュームから順番に表示させるための準備です。次に5回繰り返すループを作り、その中で方程式のポーズを2回ずつ、合計10ポーズを表示します。各繰り返しの中で「measure」というブロードキャストメッセージを送信し、音楽の1小節ごとに別のスクリプトを起動します。
「measure」ブロードキャストを受信した側のスクリプトは4回繰り返し、毎回次のコスチュームに切り替えて対応する方程式名をインデックスで読み上げ、4拍分の時間(4ビット)待機します。インデックスはfunction indexという変数で管理し、1から10まで順番に増加させます。インデックスが10を超えた場合には1にリセットする条件分岐を設けることで、リストの範囲を超えないよう制御します。音楽の再生はメインスクリプト側で行い、音楽が終わったら拍手の音を鳴らし、stop allで全スクリプトを停止します。このブロードキャストによる同期技術によって、音楽のリズムと方程式ポーズの表示が正確に連動した演出が実現します。
6.2 過去の実践事例(2017年・2018年)と学習効果の研究結果
CJ Chong: MathDanceワークショップの原型は2017年に遡ります。当時、デトロイトにあるUniversity Prep Science & Math Schoolの学生たちがこのワークショップに参加し、体を使って数式のポーズを表現するMathDanceを実演しました。その様子を収録した動画をご覧いただくと、学生たちがサークルを作り、音楽に合わせて方程式のポーズを次々と披露している姿が印象的です。このときの実践に基づく研究の結果、ワークショップに参加した学生たちの数学スコアが向上したことが確認されています。体を動かしながら方程式の形を体感するというアプローチが、数学の概念理解に実際に効果をもたらすという重要な知見です。
2018年にはワークショップにアートと音楽のコンポーネントが新たに加わりました。数式の動きに合わせた音楽を学生たち自身が作曲するという要素が追加され、数学・プログラミング・音楽・アートを横断する学際的な体験がさらに豊かになりました。学生が作曲した音楽の動画もご紹介しましたが、子どもたちが数式とリズムを結びつけながら創造的に音楽を作り上げている様子は、このワークショップの教育的可能性の広さを示しています。
6.3 10方程式版MathDanceアニメーションのデモ
CJ Chong: 今日のDay 2では、これらの歴史的な実践を踏まえたうえで、10方程式版のMathDanceアニメーションをデモとしてお見せします。対応する方程式はy=−x、y=0、y=10x、y=絶対値x、y=−絶対値x、y=x²、y=2^x、y=2^(−x)など10種類です。デモ動画では、各方程式に対応した手のポーズ画像が音楽のリズムに合わせて次々と切り替わりながら表示され、方程式名もタイミングよく読み上げられます。音楽・ポーズ・方程式名が三位一体となって展開するこのアニメーションは、前節で説明した同期プログラムの技術によって実現されています。
このフルバージョンを自分で実装するためには、さらにいくつかのScratchスキルが必要になります。まず各方程式のポーズに対応したコスチューム(手の形の画像)を10種類用意することです。これらのコスチューム画像はスライドPDFのリンクからダウンロードできます。次に音楽ファイルの同期コードを自力で書く時間が今日のワークショップ内では取れないため、完成済みのScratchコードを私のPDFハンドアウトのリンクからダウンロードして参照・活用してください。コードをダウンロードして動作を確認し、その構造を読み解くことで、ブロードキャストによる同期技術の理解がいっそう深まります。ぜひ手元で動かしながら確認してみてください。
7. ポーズモデルの活用と発展課題
7.1 画像モデルとポーズモデルの比較・ポーズモデルの作成手順と注意点
CJ Chong: ここまで画像モデルを使ってきましたが、Teachable Machineにはもう一つ「ポーズモデル」という種類のモデルがあります。画像モデルとポーズモデルの違いを整理しておきましょう。画像モデルはウェブカメラで撮影した画像全体をそのまま分類するのに対し、ポーズモデルは目・鼻・耳・肩・肘・手首といった体の関節点をリアルタイムで検出し、それらの点を線で結んだ骨格情報をもとに分類を行います。実際にポーズモデルを使うと、カメラ映像の上に関節点と接続線がオーバーレイ表示されるのが確認できます。
二つのモデルの特性の違いも重要です。ポーズモデルは人体の姿勢推定に特化しているため、リアルタイム処理能力が高く、汎用的な画像モデルと比べて少ないサンプル数で学習できるという利点があります。一方で照明の変化や背景の違いに敏感という弱点もあります。用途に応じて使い分けることが大切です。
Teachable Machineでポーズモデルを作成する手順は、画像モデルとほぼ同じです。「Get Started」からプロジェクトの種類を選ぶ際に「Pose Project」を選択するだけで、それ以降のサンプル収集・訓練・エクスポートの流れは画像モデルと変わりません。ただしサンプル収集の際に一点重要な注意があります。関節点が正しく検出されているサンプルのみを使うということです。例えば右手を上げるポーズのサンプルを収集する際、手首の関節点が検出されていない画像が混入していた場合は必ず削除してください。私がライブデモで実際に確認したところ、手首が認識されていないサンプルでは骨格の接続が途切れており、そのような不良サンプルを残したままにすると認識精度が著しく低下します。収集後の品質チェックは画像モデル以上に丁寧に行う必要があります。
7.2 ポーズモデルを使ったデモアプリと応用可能性
CJ Chong: ポーズモデルの動作を確認するために、私が事前に作成したデモアプリを紹介します。このアプリは「left up(左手を上げる)」「right up(右手を上げる)」「none(何もしない)」という3クラスのポーズモデルを使ったシンプルなプログラムです。Scratchコードの構造は画像モデルを使ったアプリと基本的に同じで、透明度を0にしてカメラをオンにした後、永久ループの中で推論を繰り返し、labelが「left up」であれば「あなたの左手が上がっています」、「right up」であれば「あなたの右手が上がっています」と読み上げます。いずれの場合もconfidenceが75%を超えている場合のみ判定するという条件を設けています。
このデモアプリをScratchに読み込んで実際に動かしてみると、右手を上げると「your right hand is up」、左手を上げると「your left hand is up」と正確に読み上げられることが確認できました。シンプルな3クラス構成ながら、リアルタイムで体の動きを認識して応答するアプリが実現できています。このScratchコードは私のPDFハンドアウトのリンクからダウンロードできますので、ぜひ手元で動かしてみてください。
ポーズモデルを活用すると、体の動きを認識するさまざまなアプリを開発できます。特に私が強くお勧めしたい応用例は、正しいフォームの運動をカウントするアプリです。例えばスクワットの場合、正しいフォームのスクワットのポーズだけをサンプルとして学習させ、そのポーズが認識されたときのみカウンターを増やすというロジックを実装します。不正確なフォームではカウンターが増えないため、フォームの矯正ツールとしても機能します。同じ発想でプッシュアップやシットアップのカウントアプリも実現できます。体育の授業やリハビリテーションの場面での活用も十分に考えられる、実用性の高い応用例です。
7.3 発展課題・修了証の取得・ライセンスとリソースへのアクセス
CJ Chong: 今日のワークショップを通じてMathDanceゲームアプリの基本版が完成しました。さらに発展させたい方のために自己学習課題を用意しています。今日実装した4方程式(y=0、y=x、y=−x、y=10x)に加えて、y=x²、y=絶対値x、y=−絶対値x、y=2^x、y=2^(−x)、そしてもう一つの方程式を追加し、合計10方程式に対応したアプリを完成させてください。完成したらスクリーン録画ソフトウェアを使ってデモ動画を作成し、その動画リンクを私に送ってください。あるいはScratchのプロジェクトファイル(.sb3形式)をそのまま送っていただいても構いません。確認が取れた方には修了証(PDF形式)を発行します。
なお一人で取り組む場合、10方程式のポーズを手だけで表現するには工夫が必要です。その際にはUSBフットペダルスイッチの活用をお勧めします。足でペダルを踏むことで次の問いに進むといった操作が可能になります。また二人一組のチームプロジェクトとして取り組むのも非常に有効です。一人がポーズを担当し、もう一人がプログラムを操作するという役割分担で、より多彩な方程式の表現が可能になります。
本ワークショップのすべての資料はCC BY 4.0ライセンスのもとで公開されています。このライセンスは、元の作成者に適切なクレジットを表示する限り、商用利用を含むあらゆる目的での利用・改変・再配布を誰にでも許可するものです。世界中の誰もがこの教材を自由に活用して授業やワークショップを開催できます。スライドのPDF・Scratchコード・音楽ファイルはRobo FestウェブサイトおよびAI for Goodのリソースページ、ニューラルネットワークのプログラムページから入手できます。
Julius Caesar: CJ先生、一点補足させてください。あるアフタースクールのグループがこのMathDanceワークショップを自分たちの場でもやってみたいと相談してきています。もしそのような依頼があれば、ぜひ私のプレゼンテーションを活用してもらえると思います。
CJ Chong: もちろんです。今日の発表資料はニューラルネットワークのリソースページとAI for Goodウェブサイトのプログラムページに掲載されていますので、興味のある方はどなたでもアクセスして活用いただけます。ぜひ多くの場でMathDanceを広めていってください。本日参加してくださった皆さん、そしてDr. Zhou、Julius、Gregoryへの感謝を申し上げます。10方程式バージョンの動画を送ってくれた方には修了証をお送りしますので、ぜひ挑戦してみてください。
