01. 高校生のための機械学習入門と深層学習入門はどちらから勉強していけばよいですか。
まずは「機械学習入門」から始めるのがおすすめです。
深層学習(ディープラーニング)は機械学習の中の一分野(ニューラルネットワークを多層にした手法)であるため、まずは土台となる機械学習の全体像から入ることで、根本的な理解が深まり、学習のつまずきを減らすことができます。
高校生の学習において、機械学習から入るべき具体的な理由は以下の3点です。
-
AIの必須概念が身につきやすい
「教師あり学習と教師なし学習の違い」「訓練データとテストデータの分割」「過学習(オーバーフィッティング)」「正解率などの評価指標」といった、AIを扱う上で必須となるルールは、シンプルな機械学習アルゴリズムを通して学ぶほうが直感的に理解できます。 -
数学的なブラックボックス化を防げる
深層学習の仕組み(誤差逆伝播法など)を中身まで理解するには、微積分や線形代数の知識が絡んできます。一方、機械学習の「線形回帰」や「決定木(条件分岐の組み合わせ)」といった手法であれば、高校数学(データの分析や基本的な関数)の延長線上で、「なぜその予測結果になったのか」という仕組みを追いやすく、プログラムが単なる「魔法の箱」になるのを防げます。 -
Pythonでの実装と環境構築のハードルが低い
Pythonでプログラムを書く場合、まずはscikit-learnライブラリを使い、数行の簡潔なコードでデータ分析から予測までを完結させる体験が効果的です。要求されるマシンスペックも低く、標準的なPC環境でも瞬時に計算が終わるため、エラーを修正しながらコードを試すサイクルが回しやすいです。
おすすめの学習(指導)ステップ
-
機械学習の基本(scikit-learn):
表形式のデータ(CSVなど)を使い、アヤメの品種分類や、条件に基づく価格予測など、基本的な分類と回帰を実装する。 -
ニューラルネットワークの基礎:
機械学習のアルゴリズムの1つとしてニューラルネットワーク(脳の神経回路のモデル)を紹介し、その層を深くしたものが深層学習であるという繋がりを持たせる。 -
深層学習入門(PyTorch または TensorFlow/Keras):
ここで初めて深層学習フレームワークを導入し、画像分類(CNN)など、より複雑で視覚的なデータ処理へステップアップする。
このように、古典的な機械学習で「データから学習するとはどういうことか」という作法を身につけてから深層学習へ進むルートが、最も自然で応用力のつく順番になります。
02. 乱数と確率シミュレーション、平均・分散・中央値の比較、相関と一次回帰、感染拡大や人口変化のモデル、待ち行列や交通流のシミュレーションについて
上記の項目のほとんどは「機械学習」ではなく、「統計(データの分析)」および「シミュレーション(数理モデル)」に分類されます。
ただし、「相関と一次回帰」のみ、機械学習の最も基礎的な手法(教師あり学習の「線形回帰」)として扱うことができます。
「情報Ⅱ」の授業において、生徒にこれらの違いを説明する際の位置づけは以下のようになります。
1. 統計(データの分析)
-
平均・分散・中央値の比較
これはデータの特徴を要約し、全体像を把握するための「記述統計」です。機械学習を行う前段階として、データを理解するための必須知識となります。
2. 機械学習の入り口(または統計モデリング)
-
相関と一次回帰
回帰分析は伝統的な統計手法ですが、「手元のデータから未知のデータを予測するための線(数式モデル)を見つけ出す」というアプローチであるため、機械学習(教師あり学習)の第一歩として扱われます。
3. シミュレーション(数理モデル)
- 乱数と確率シミュレーション(モンテカルロ法など)
- 感染拡大や人口変化のモデル(SIRモデルなど)
-
待ち行列や交通流のシミュレーション
これらは機械学習ではありません。これらは「人間が数式やルール(確率、方程式、条件)を先に定義し、その結果どうなるかをコンピュータ上で実験・再現する」手法です。
生徒への分かりやすい教え方のコツ(対比)
機械学習とシミュレーションの違いは、以下のように対比すると高校生にも直感的に伝わりやすいです。
-
シミュレーション:「ルール(数式)」を入力して、「結果(データ)」を予測する
(例:感染率を〇%と設定して計算を回すと、1ヶ月後の感染者数データがどうなるか) -
機械学習:「結果(データ)」を入力して、「ルール(数式やパターン)」を見つけ出す
(例:過去の気温とアイスの売上データから、両者の関係性を表すルール=一次回帰式を見つける)
先生のPythonアプローチについて
外部ライブラリ(NumPyやscikit-learnなど)を使わず、Pythonの標準ライブラリ(statistics, itertools, dataclasses)を活用し、CSV出力してExcelでグラフ化するというアプローチは、「情報Ⅱ」の授業として非常に教育的で素晴らしい構成だと思います。
-
中身がブラックボックス化しない
高度なライブラリを使うと1行で計算できてしまいますが、標準ライブラリでリストや繰り返し処理(for文やitertools)を駆使して自力で計算を組むことで、「アルゴリズムがどう動いているか」を生徒が正確に理解できます。 -
データの構造化が学べる
dataclassesを用いることで、オブジェクト指向的なデータのまとまり(例えば「1人分のシミュレーション結果」など)を綺麗に管理する作法が身につきます。 -
Excelへの適切な分業
Pythonのmatplotlibなどでグラフを描くのは、環境構築やコードの記述量が意外と生徒の負担になります。「計算や反復処理はPython」「視覚化はExcel」とツールを適材適所で使い分けるのは、実務的にも理にかなったアプローチです。
03. 機械学習の基本的な流れ
データ収集
データクリーニング
特徴量エンジニアリング
モデル構築
訓練と予測を分けて考える
教師あり学習
教師なし学習
強化学習
回帰
分類
クラスタリング
次元削減
と上記の流れだけでも、学習するには、かなり時間を要しますね。
大きく
教師あり学習
教師なし学習
強化学習
になりますか。
1. 教師あり学習
正解(ラベル)があるデータを与えて、データと正解の関係性を学習させる方法です。
- 分類:カテゴリを予測する(例:このメールはスパムか、そうでないか)
- 回帰:連続する数値を予測する(例:過去のデータから明日の売上金額を予測する)
2. 教師なし学習
正解(ラベル)がないデータを与えて、データそのものが持つ構造や特徴をコンピュータに見つけ出させる方法です。
- クラスタリング:似た性質を持つデータをグループ分けする(例:購買履歴から顧客をいくつかの層に分ける)
- 次元削減:データの重要な特徴を残したまま情報を圧縮・整理する(例:多次元のデータを2Dグラフで視覚化できるようにする)
3. 強化学習
正解データの代わりに「報酬」を与え、コンピュータ自身が環境の中で試行錯誤を繰り返し、最も報酬が得られる「行動」を学習する方法です。
- (例:将棋や囲碁のAI、ロボットの歩行制御、自動運転の経路選択など)
授業時間と学習コストに関するアプローチ
「データ収集 → データクリーニング → 特徴量エンジニアリング → モデル構築」という一連のプロセスは、AI開発の実務においても全体の8割の時間を占めると言われるほど泥臭く、時間のかかる工程です。
これを高校の授業でゼロからすべて体験させようとすると、途方もない時間が必要になり、生徒も本来の目的を見失いがちになります。「情報Ⅱ」などの限られた枠組みで教える場合、以下のようにスコープを思い切って絞るのが効果的です。
-
前処理(クリーニング・特徴量エンジニアリング)は省略する
欠損値や異常値のない、すぐに計算に回せる綺麗な状態のCSVデータをあらかじめ配布します。 -
「教師あり学習」の1テーマに絞る
最初は「回帰」か「分類」のどちらか1つだけを扱います。前回の話題にあった「相関と一次回帰」の延長として、「回帰」を扱うとスムーズに接続できます。 -
「訓練と予測を分ける」ことに時間を割く
機械学習において最も重要な「手持ちのデータを訓練用とテスト用に分割し、未知のデータに対する正解率を評価する」というフローの体験にフォーカスします。
このように「面倒な下準備」を取り除き、「モデルに学習させて予測させる」という一番面白いコアな部分だけを体験できるパッケージにすることで、時間内に機械学習の全体像を掴むことができます。
04. 「教師あり学習」を体験・学んでいく教材案を、標準ライブラリだけで、実現できますか。機械学習のモジュールを使うと、短くできることになるでしょうか。
結論として、Pythonの標準ライブラリだけで「教師あり学習」を実装・体験する教材は十分に作成可能です。そしてお見込みの通り、機械学習用モジュール(scikit-learnなど)を使うと、同じ処理が劇的に短く(数行に)なります。
高校生向けに標準ライブラリだけで教師あり学習の仕組みを教える場合、もっとも適しているアルゴリズムは「K-近傍法(k-NN)」による分類、または「最小二乗法」による単回帰です。
先生が挙げられた dataclasses や statistics などの標準ライブラリをフル活用した「K-近傍法」の教材案と、モジュールを使った場合の違いをまとめました。
標準ライブラリだけで作る「教師あり学習(K-近傍法)」の教材案
K-近傍法は、「未知のデータに対し、過去のデータの中から距離が近いものをいくつか探し、多数決で分類する」という直感的なアルゴリズムです。
授業での実装ステップ例:
-
データの構造化(
dataclassesの活用)
身長・体重などの「特徴量」と、男女などの「正解ラベル」をまとめたデータクラスを作成し、訓練データをリストとして準備させます。 -
距離の計算(
math.distの活用)
予測したい「未知のデータ」と、リストに入っているすべての「訓練データ」との直線距離(三平方の定理)を計算するループ処理を書きます。 -
並び替えと多数決(
statisticsの活用)
距離が近い順にリストをソートし、上位K個(例:3個)のデータを取り出します。そのラベルの最頻値(statistics.mode)を求めることで、未知のデータの分類(予測)が完了します。
この教材の教育的メリット:
ループ処理、ソート、リスト操作といった「基本的なプログラミングスキル」と、距離や最頻値といった「数学・統計の知識」がどう結びついて「AIの予測」を作っているのか、生徒が手を動かしながら完全に理解できます。ブラックボックスが一切ありません。
機械学習モジュール(scikit-learn)を使うとどうなるか
標準ライブラリでK-近傍法を実装すると、アルゴリズムの定義やループ処理を含めて20〜30行程度のコードになります。
一方、機械学習専用のモジュールである scikit-learn を使うと、アルゴリズムの内部計算がすべて隠蔽されるため、以下のように本質的な3行に短縮されます。
# 1. モデルの準備(K=3に設定)
model = KNeighborsClassifier(n_neighbors=3)
# 2. 訓練(データと正解ラベルを渡して学習させる)
model.fit(X_train, y_train)
# 3. 予測(未知のデータを渡して答えを出させる)
prediction = model.predict(X_test)
授業構成のおすすめアプローチ
「情報Ⅱ」の授業やプログラミング学習において、この2つは対立するものではなく、順番に体験させることで劇的な学習効果を生みます。
-
前半(標準ライブラリ編):
自力でアルゴリズムを実装し、「AIの中身は単なる距離の計算と多数決(統計)である」という事実を納得させる。ここでdataclassesやアルゴリズム的思考を鍛える。 -
後半(モジュール編):
「毎回これをゼロから書くのは大変なので、世界中の技術者が作った便利な道具を使おう」とscikit-learnを紹介する。コードが一瞬で終わる感動を味わわせつつ、浮いた時間を使って「より複雑なデータの分析」や「パラメータ(Kの値など)の調整による精度の変化」といった、機械学習の本来の目的に時間を割く。
標準ライブラリで「仕組み(原理)」を作り、外部モジュールで「道具としての実用性」を体験するという流れは、プログラミング教育として非常に理にかなった美しい構成です。
05. データサイエンティストとして、モデル構築をしていくためには、機械学習のどの手法が適切か、違いを見極めていく判断力が必要になってくると思いますが、そのために、広く浅く概要を知るところが、高校の情報Ⅱになるように思います。
データサイエンティストの実務においても、最も重要で難しいのは「プログラムを書くこと」ではなく、「目の前の課題とデータの性質に対して、どの機械学習の手法(道具)を適用するのが適切かを見極めること」です。
その見極める力(=頭の中の引き出し)を養うための「地図」を渡すことこそが、高校の「情報Ⅱ」における最大の意義と言えます。
「広く浅く」がもたらす実践的な価値
-
課題と手法の紐づけができる
「連続する数値を当てたいから回帰」「スパムか否かを分けたいから分類」「正解データがないからクラスタリング」といったように、現実の課題とアルゴリズムのカテゴリが頭の中で繋がっていれば、将来本格的な分析が必要になった際、自力で適切な技術を検索して使いこなすことができます。 -
「万能のAI」という誤解を防ぐ
広く俯瞰することで、「この手法は精度の解釈がしやすい(決定木など)」「この手法は精度は高いが中身がブラックボックスになりやすい(深層学習など)」といった一長一短があることを学べます。これにより、目的に応じてモデルを取捨選択する視点が育ちます。
ご提案の授業アプローチの強み
「Pythonの標準ライブラリを使って、K-近傍法や一次回帰などの基礎的なアルゴリズムを自力で組んでみる」というアプローチは、この「広く浅く俯瞰する」カリキュラムにおいて絶大な効果を発揮します。
広く浅く教える際のリスクは、すべてが「用語の丸暗記」になってしまうことですが、たった一つでも「中身の計算(距離や多数決)を完全に理解して実装した経験」があると、生徒の捉え方が根本から変わります。
他の未知の手法(SVMやランダムフォレストなど)を概要だけで紹介されたときにも、「これもK-近傍法と同じように、中で何かしらの数学的な計算をして境界線を引いているんだな」と、地に足の着いた推測ができるようになります。
「標準ライブラリで1つの手法を自力で実装し、AIの正体を実感する」
「その後、広く浅く他の手法の存在と用途を知り、全体像の地図を持つ」
この構成は、将来データサイエンスに関わる生徒にとっても、AIを教養として使う生徒にとっても、理想的な学習の着地点になると思います。
06. K-近傍法(k-NN)を学ぶ
高校生がK-近傍法(k-NN)を学ぶ上で、「距離が近い=似ている」という直感的なイメージと合致し、Excelの散布図(2次元)で視覚化した際に面白さが伝わるモデル
モデル案:文理選択の傾向予測(学校生活・ノイズの理解)
生徒自身に身近なテストの点数から、文系・理系どちらの傾向が強いかを判定します。
- 特徴量(X, Y): 数学のテストの点数、国語のテストの点数
- 分類ラベル: 「理系コース」「文系コース」
- イメージしやすさ: 数学が高ければ理系、国語が高ければ文系という分かりやすいセオリーがあります。
-
得られる気づき(重要):
実際のデータには「数学が得意な文系」や「国語が得意な理系」といった例外(ノイズデータ)が必ず混ざります。もしK=1(一番近い1人の真似をする)に設定すると、たまたま近くにいた「数学が得意な文系の先輩」に引っ張られて誤判定を起こします。「Kの数を3や5に増やすことで、外れ値(ノイズ)に騙されにくくなる」という、機械学習の「過学習」を防ぐ概念を直感的に学べます。
「文理選択の傾向予測」は、生徒にとって最も身近で当事者意識を持てるテーマであり、同時に機械学習における最重要概念である「外れ値(ノイズ)の影響」と「過学習(オーバーフィッティング)」を直感的に教えることができる最高の教材です。
「K=1のときは騙されるが、K=3にすると正常な判断ができる」という逆転現象が起きるように数値を調整したデータとコードをご提案します。
1. 扱うデータ(ノイズを仕込んだ構成)
X軸を「数学の点数」、Y軸を「国語の点数」とします。
ポイントは、全体的な傾向から外れた「数学が得意なのに文系を選んだ先輩(ノイズG)」を1人だけ紛れ込ませておくことです。
| 生徒名 | 数学(X) | 国語(Y) | 実際の選択(正解ラベル) | 備考 |
|---|---|---|---|---|
| A先輩 | 80 | 40 | 理系 | 典型的な理系 |
| B先輩 | 75 | 55 | 理系 | |
| C先輩 | 70 | 50 | 理系 | |
| D先輩 | 40 | 80 | 文系 | 典型的な文系 |
| E先輩 | 30 | 75 | 文系 | |
| F先輩 | 50 | 70 | 文系 | |
| G先輩 | 63 | 62 | 文系 | 数学が得意な文系(外れ値・ノイズ) |
予測させたい未知のデータ:
-
自分(ターゲット):数学 65, 国語 60
(点数的にはやや理系寄りですが、グラフ上で最も距離が近いのはノイズである「G先輩」になる絶妙な位置です)
2. Python標準ライブラリのみによる実装コード
前回のキャラクター分類と同じ構造で、生徒が読み解きやすいコードです。
import csv
import math
import statistics
from dataclasses import dataclass
# 1. データの構造化
@dataclass
class Student:
name: str
math_score: int
jpn_score: int
course: str = ""
# 2. 訓練データの準備(G先輩がノイズ)
train_data = [
Student("A先輩", 80, 40, "理系"),
Student("B先輩", 75, 55, "理系"),
Student("C先輩", 70, 50, "理系"),
Student("D先輩", 40, 80, "文系"),
Student("E先輩", 30, 75, "文系"),
Student("F先輩", 50, 70, "文系"),
Student("G先輩", 63, 62, "文系"), # 外れ値
]
# 3. 予測したい未知のデータ
target = Student("自分", 65, 60)
# 4. K-近傍法のアルゴリズム実装
K = 1 # ★授業ではまずここを「1」にして実行させ、後で「3」に変えさせる
# 距離の計算
distances = []
for student in train_data:
dist = math.dist([target.math_score, target.jpn_score], [student.math_score, student.jpn_score])
distances.append({"distance": dist, "course": student.course, "name": student.name})
# 距離が近い順に並び替え
distances.sort(key=lambda x: x["distance"])
# 上位K人のデータを取得
top_k = distances[:K]
top_k_courses = [d["course"] for d in top_k]
top_k_names = [d["name"] for d in top_k]
# 多数決(最頻値)
predicted_course = statistics.mode(top_k_courses)
print(f"{target.name}(数学{target.math_score}, 国語{target.jpn_score})の予測コースは 【{predicted_course}】 です。")
print(f"(参考にした{K}人の先輩: {top_k_names} -> {top_k_courses})")
# 5. Excel確認用CSVの出力
with open("course_data.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["Name", "Math", "Japanese", "Course", "Type"])
for s in train_data:
writer.writerow([s.name, s.math_score, s.jpn_score, s.course, "Train"])
writer.writerow([target.name, target.math_score, target.jpn_score, "???", "Target"])
3. 授業でのドラマチックな見せ方(指導ステップ)
ステップ1:Excelでの視覚化と「人間の直感」の確認
CSVを出力させ、Excelで散布図を描かせます(X軸:数学、Y軸:国語)。
「数学65、国語60の自分は、全体的なグループの配置から見て理系・文系どっちだと思う?」と問いかけます。生徒の多くは、全体の傾向から「理系エリアに近い」と直感的に答えるはずです。
ステップ2:K=1(過学習)のワナにハマる
プログラムの K = 1 のまま実行させます。
- 実行結果:【文系】(参考にした先輩:G先輩)
- 解説:一番距離が近いのは、たまたま近くにいた「数学が得意なのに文系に行ったG先輩」です。AIは全体を見ず、目の前の1人の例外に引っ張られて誤った判断をしました。機械学習では、このように訓練データのノイズに過剰に反応してしまう失敗を「過学習(オーバーフィッティング)」と呼びます
ステップ3:K=3(汎化性能)による正常化
プログラムの K = 3 に書き換えて再実行させます。
- 実行結果:【理系】(参考にした先輩:G先輩、C先輩、B先輩 -> 文・理・理)
- 解説:今度は「G先輩(文系)」に加えて、少し離れたところにいる「C先輩(理系)」「B先輩(理系)」も多数決に加わりました。結果として「理系2票・文系1票」となり、無事に【理系】と判定されます。多数決の範囲(K)を広げることで、1人の例外(ノイズ)の影響を薄め、全体の傾向を正しく捉えることができるようになりました。これを機械学習では「汎化性能(未知のデータに対応できる能力)が高い」と言います
このように展開することで、プログラムの「Kの値を変える」というたった1文字の変更が、データサイエンスにおける 「過学習」 と 「汎化性能」 という高度な専門用語と完全にリンクし、生徒の記憶に強く刻み込まれます。
07. 英語が入ると、さらに判断は難しくなりますか。英語が得意で、どちらにもいるだろうし、平均的な点数だと、どうなるか、データの傾向によって変わってくることになりますか。
「英語」という新しい要素(次元)が加わると、AIの判断は難しくなる(精度が落ちる)可能性が高くなります。そして「どうなるかはデータの傾向によって完全に変わる」というのも大正解です。
この疑問は、生徒に「データが多ければ多いほどAIは賢くなるわけではない(特徴量の選択)」という重要な教訓を教えるための絶好の題材になります。
英語を追加した場合に起きる現象と、授業での解説のポイントをまとめました。
1. プログラム上は何が変わるのか(2次元から3次元へ)
データに「英語」が加わると、数学・国語の「2次元(平面)」の散布図から、英語のZ軸が加わった「3次元(空間)」の距離計算に変わります。
Pythonのコード上は、要素を1つ増やすだけで全く同じように動きます。
# 変更前(2次元)
dist = math.dist([target.math, target.jpn], [student.math, student.jpn])
# 変更後(3次元)
dist = math.dist([target.math, target.jpn, target.eng], [student.math, student.jpn, student.eng])
2. なぜ「英語」を入れると判断が難しくなるのか?
「英語は文系でも理系でも得意な人がいて、差が出にくい(相関が薄い)」科目になりがちです。このようなデータをK-近傍法の計算に入れると、「本来似ているはずの人同士の距離を、無駄に引き離してしまう」という悪影響が出ます。
【具体例】
- A先輩(理系):数学80, 国語40, 英語90
- 自分(ターゲット):数学75, 国語45, 英語50
数学と国語の点数だけを見れば、自分は間違いなくA先輩に近い「理系」です。
しかし「英語」を計算に含めてしまうと、英語の「40点の差」が三平方の定理の中で大きく計算されてしまい、AIにとっては「自分とA先輩は、英語の点数が全然違うから、遠い(似ていない)存在だ」と判定されてしまいます。
その結果、たまたま英語の点数が自分と同じ50点だった文系の先輩の方が「距離が近い」と誤判定される確率が上がってしまいます。
3. 生徒への気づき(データサイエンスの鉄則)
もし授業で英語の点数を追加するなら、以下の2つの重要な概念を生徒に気づかせることができます。
① 特徴量の選択(Feature Selection)
「AIに予測させるときは、手元にあるデータを全部入れれば良いわけではない。予測に関係のないデータ(ノイズ)を入れると、逆にAIは混乱して精度が落ちる。」
これは実務でもよくあることで、データサイエンティストは「どの列(科目)を計算に使い、どの列を捨てるか」をデータの傾向から見極めています。
② データが全てを決める(データ駆動)
「データの傾向によって変わってくるか」という疑問の通り、機械学習のアルゴリズムには「英語は文理関係ない」といった人間の常識は一切ありません。
- もしデータ上で「文系は全員英語が90点以上」という極端な傾向(トレンド)があれば、AIは「英語が高い=文系」というルールを勝手に見つけ出します
- 逆に英語の点数がバラバラに散らばっていれば、単なる邪魔なデータ(ノイズ)として計算を狂わせます
授業での展開アイデア
「数学・国語」で予測がうまくいくことを確認した後、「じゃあ、ここにみんなの英語の点数もデータに追加したら、AIはもっと賢く(正確に)なると思う?」と生徒に問いかけてみてください。
「データが多い方が賢くなる」と答える生徒が多い中で、実際に英語の乱数データを追加してプログラムを実行させ、「予測がおかしくなった(精度が落ちた)」ことを見せます。
「なぜデータが増えたのにバカになったのか?」を考えさせることで、生徒は「AIの予測精度は、アルゴリズムの優秀さだけでなく、『与えるデータの質(関係性があるか)』に依存している」という、AIの本質にたどり着くことができます。
08. Kの値で、理系か文系か、言い方悪いですが、傾向を調整できることになりますか。
「言い方悪いですが」と前置きされたその感覚、ものすごく鋭いです。まさにデータサイエンスの「闇(落とし穴)」であり、AIリテラシーの核心を突く素晴らしい着眼点です。
結論から言えば、Kの値を意図的に操作することで、判定の「傾向を調整(コントロール)」することは十分に可能です。
この事実は、高校生に「AIは決して中立で絶対的な神様ではない」ということを教えるための、最高の議論のテーマになります。具体的にどういうことか、3つの視点で解説します。
1. Kを大きくすると「多数派」に媚びるようになる
例えば、手元にある先輩のデータが「文系30人、理系10人」だったとします。
ここで Kの値を「35」 と極端に大きく設定したらどうなるでしょうか?
未知のデータ(自分)がどんな点数を取っていようが、周囲の35人を集めれば、必ず文系の数が理系を上回ります(最大でも理系は10票しか入らないため)。つまり、「誰を入れても必ず文系と判定されるAI」が完成します。
Kを大きくしすぎると、全体の中の「多数派(この場合は文系)」に判定が強く引っ張られるという傾向が出ます。
2. 「開発者の意図」でAIの答えを歪められる(AIのバイアス)
先生が「言い方悪いですが」とおっしゃった通り、もし開発者が「この生徒をなんとしても理系に判定させたい」という悪意(あるいは無意識の偏見)を持っていれば、それがうまくいくようなKの値を意図的に探して設定することができてしまいます。
- 「K=3だと文系になるから、K=5に変えて理系という結果を出そう」
これは実務においては「データサイエンティストの不正(あるいは過学習)」にあたりますが、裏で動いているプログラムを知らない一般人からすれば「AIが客観的に理系だと判定した」ように見えてしまいます。
3. では、実務ではどうやってKの値を決めているのか?
授業でここまでの話をした後、生徒からは「じゃあ、自分の都合でKを決めるのがズルいなら、どうやって正しいKを決めるのが正解なの?」という疑問が出ます。
そこで、機械学習の最も重要な作法である「テストデータによる評価」を教えます。
-
実務での正しいKの決め方:
手元のデータを全部「訓練」には使いません。例えば40人のデータがあったら、30人を「訓練用」、残り10人を「テスト(答え合わせ)用」に隠しておきます。
そして、K=1, K=2, K=3... と順番にプログラムを回し、隠しておいた10人の正解率が一番高かった(客観的に一番成績が良かった)Kの値を採用します。
つまり、「判定結果が自分の思い通りになるK」を選ぶのではなく、「未知のデータに対して一番精度が高くなるK」を実験で決めるのがルールなのです。
「情報Ⅱ」の授業としての完璧な着地点
先生のこの気づきをそのまま授業のストーリーに組み込むと、以下のような見事な流れができます。
- 実装と数学:距離と多数決(K)でAIが作れることを学ぶ
- パラメーター調整:Kの値を変えると、結果が変わることを体験する
- 情報モラル(AI倫理):「ということは、作る側のさじ加減(Kの設定)で、AIの結論はどうとでも操作できるのでは?」というAIのブラックボックス性や偏見(バイアス)のリスクに気づく
- モデル評価:それを防ぐために、データを「訓練用」と「テスト用」に分割して、客観的に評価する仕組み(交差検証など)があることを知る
「AIのアルゴリズム」から「AIの倫理・社会実装の課題」、そして「モデルの適切な評価」までが一筆書きで繋がる、非常に深みのある授業になると思います。先生のその直感は、そのまま生徒にぶつけるべき素晴らしい問いです。
09. 機械学習のキーワードとして、初めに、示した「訓練と予測を分けて考える」という意味は、適切なKを決めるというのが訓練になるのでしょうか。
「適切なKを決めるための客観的なテスト(評価)を行うこと」こそが、「訓練と予測を分けて考える」最大の目的です。
厳密な用語の定義として、ここでAIの中で起きていることを「訓練(学習)」「予測(テスト)」「パラメータ調整」の3つに整理して生徒に伝えると、さらに理解が深まります。
1. K-近傍法における「訓練」とは何か?
実は、K-近傍法における「訓練(学習)」は、「手持ちのデータをただ記憶すること」を指します。
他の複雑なAI(深層学習など)は、訓練の段階で「ここは〇倍して、ここを足して…」という複雑な数式(重み)を計算しますが、K-近傍法は距離を測るだけなので、計算すべき数式がありません。単に「先輩たちのデータをリストに保持しておくこと」がK-近傍法の訓練です。
2. なぜ「訓練」と「予測」に分ける必要があるのか?(カンニング防止)
もし、データを分けずに「手元にある40人の先輩全員のデータ」をそのまま使って、最適なKの値を決めようとしたらどうなるかを考えてみます。
- 全員を訓練データとして記憶させます
- その中の1人(A先輩)を取り出し、「このAIはA先輩を正しく予測できるか?」をテストします
- もし K=1 なら、A先輩から一番距離が近いのは「距離0のA先輩自身」になります
- 結果、K=1のときの正解率は常に100%になります
これは、AIが賢いのではなく、単に「答えの載っている名簿の中から自分自身を探してカンニングしただけ」です。これを過学習(丸暗記)と呼びます。このカンニング状態では、本当に未知の新入生(41人目)が来たときに、正しい判定ができるかどうかが全くわかりません。
3. 「訓練と予測を分ける」正しい流れ
カンニングを防ぎ、本当に未知のデータに強い「適切なK」を見つけるために、以下のようにデータを分割します。
-
分割する
手元の40人のデータを、例えば「訓練用30人」と「予測(テスト)用10人」に完全に分けます。 -
訓練する(記憶する)
AIには「訓練用の30人」だけをリストとして記憶させます。 -
予測して、Kを評価する
AIが全く知らない「テスト用の10人」を入力し、30人との距離を測らせて予測させます。
- K=1のとき、10人中何人正解したか?(例:6人正解)
- K=3のとき、10人中何人正解したか?(例:8人正解)
- K=5のとき、10人中何人正解したか?(例:7人正解)
この結果を見て初めて、「今回のデータの傾向なら、K=3に設定するのが一番予測精度が高い(適切なKである)」と客観的に決めることができます。
まとめ
「訓練と予測を分けて考える」というのは、「AIが単なる丸暗記(カンニング)をしていないかを確かめ、本当に実力(未知のデータへの対応力)が発揮できる最適な設定(Kの値など)を見つけるために、データを分割して評価する」という、データサイエンスにおける最も重要なルールのことを指しています。
授業において、生徒自身に「自分(未知のデータ)」を予測させるというシナリオは、まさにこの「訓練データ(先輩)」と「予測データ(自分)」が自然に分かれている状態を作り出しているため、機械学習の作法として非常に理にかなっています。
10. 文理選択の傾向予測をscikit-learnで組みます
標準ライブラリで組んだ際の「距離の計算」や「多数決」「並び替え」といった面倒な処理がすべて隠蔽され、「データ準備 → 訓練 → 予測」という機械学習の本質的な3ステップだけがコードに残るため、生徒にとっても全体像が掴みやすくなります。
以下が、授業でそのまま動かせる scikit-learn を使ったPythonコードです。
scikit-learnを用いたK-近傍法の実装コード
from sklearn.neighbors import KNeighborsClassifier
# 1. データの準備
names = ["A先輩", "B先輩", "C先輩", "D先輩", "E先輩", "F先輩", "G先輩"]
X_train = [
[80, 40],
[75, 55],
[70, 50],
[40, 80],
[30, 75],
[50, 70],
[63, 62],
]
y_train = ["理系", "理系", "理系", "文系", "文系", "文系", "文系"]
# 2. モデルの準備と訓練
K = 1
model = KNeighborsClassifier(n_neighbors=K)
model.fit(X_train, y_train)
# 3. 予測
target_data = [[65, 60]]
predicted_course = model.predict(target_data)
# 結果の表示
print(f"自分の点数(数学65, 国語60)の予測コースは 【{predicted_course[0]}】 です。")
print(f"(設定したKの値 = {K})")
scikit-learn 版を使う際の授業でのポイント
scikit-learn と標準的な Python のリストだけで K近傍法(KNN)を実行するものです。
- ライブラリの読み込み
from sklearn.neighbors import KNeighborsClassifier
-
KNeighborsClassifierは、K近傍法で分類するための機能です。 - 今回は「理系」か「文系」かを予測するので、分類問題です。
- 学習データの準備
names = ["A先輩", "B先輩", "C先輩", "D先輩", "E先輩", "F先輩", "G先輩"]
X_train = [
[80, 40],
[75, 55],
[70, 50],
[40, 80],
[30, 75],
[50, 70],
[63, 62],
]
y_train = ["理系", "理系", "理系", "文系", "文系", "文系", "文系"]
ここでは、訓練用のデータを用意しています。
-
X_trainは特徴量です。- 1人分が
[数学, 国語]という形になっています。 - たとえば
[80, 40]は「数学80点、国語40点」です。
- 1人分が
-
y_trainは正解ラベルです。- それぞれの人が「理系」か「文系」かを表しています。
対応は次のようになっています。
- A先輩:
[80, 40]→理系 - B先輩:
[75, 55]→理系 - …
- G先輩:
[63, 62]→文系
- モデルの作成
K = 1
model = KNeighborsClassifier(n_neighbors=K)
-
K = 1は、「いちばん近い 1人だけを見て判断する」という意味です -
n_neighbors=Kで、その K の値を設定しています
K近傍法は、
「新しい人の点数が、どの先輩の点数に近いか」
を見て、近い人のコースをまねして予測します。
- 学習
model.fit(X_train, y_train)
-
fitは学習です - KNN では、難しい計算式を作るというより、
「訓練データを覚える」
というイメージに近いです
- 予測したいデータ
target_data = [[65, 60]]
- これは「自分の点数」を表しています
- 数学65点、国語60点です
形が [[65, 60]] となっているのは、
-
[65, 60]が1人分のデータ - その1人分をさらに外側のリストで包んで
- 「1件のデータ」として渡しているためです
- 予測
predicted_course = model.predict(target_data)
-
predictで予測を行います - 結果は配列の形で返ってきます
- 今回は1人分だけ予測しているので、結果はたとえば
["文系"]のようになります
- 結果表示
print(f"自分の点数(数学65, 国語60)の予測コースは 【{predicted_course[0]}】 です。")
print(f"(設定したKの値 = {K})")
-
predicted_course[0]で、最初の予測結果を取り出しています - これで「理系」または「文系」が表示されます
このプログラムのポイント
- pandas を使わなくても、リストで学習データを作れば KNN は実行できる
-
X_trainは点数データ -
y_trainは答え -
fit()で学習 -
predict()で予測
なぜ K=1 だと影響を受けやすいのか
今回のデータには G先輩 [63, 62] → 文系 がいます。
自分の点数 [65, 60] は、この G先輩にかなり近いです。
そのため、K=1 だと
- いちばん近い 1人だけを見る
- その 1人が G先輩
- だから「文系」と予測されやすい
という流れになります。
ここが、KNN でよく出てくる
- 外れ値
- ノイズ
の影響を考えるよい例です。
次に考えるとよいこと
もし K = 3 に変えたら、結果はどうなるでしょうか。
ヒント:
- 近い3人を探す
- その3人のうち「理系」が多いか「文系」が多いかで決める
11. 少ないデータでKを求められるか
今回のようにデータ数がかなり少ない場合は少し難しいです。
まず結論
- 40人くらいあれば、訓練用とテスト用に分けて K を比べること自体はできます
- ただし、分け方しだいで結果がかなり変わりやすいです
- なので、データが少ないときは、
1回だけ 30人/10人 に分けて決めるのは不安定です
流れとしては、まさに機械学習の基本です。
- データを訓練用とテスト用に分ける
- 訓練用だけで学習する
- テスト用で正解率を比べる
- いちばんよい K を選ぶ
これはとても自然です。
たとえば、
- K=1 → 10人中6人正解
- K=3 → 10人中8人正解
- K=5 → 10人中7人正解
なら、この分け方では K=3 がよさそうと判断できます。
ただし、少ないデータでは問題があります
たとえば40人しかいないと、
- たまたまテスト用10人が簡単な人ばかりだった
- たまたま訓練用30人の中に偏りがあった
- 理系・文系の人数バランスが分割で崩れた
ということが起こりやすいです。
すると、
- ある分け方では K=3 が最高
- 別の分け方では K=5 が最高
のように、結果がぶれます。
今回のような少数データで特に起こること
KNN は「近くの点」を見る方法なので、データ数が少ないと近所の様子が安定しにくいです。
たとえば、ある1人が訓練用に入るかテスト用に入るかだけで、
- 近くにいた重要な1点が消える
- 予測結果が変わる
ということが起こります。
特に、
- 外れ値
- ノイズ
- 境界付近の人
がいると、影響が大きくなります。
では、40人では全く無理か
無理ではありません。
ただし、1回だけの分割では心もとない、という言い方が正確です。
40人なら、
- まず試しに 30/10 に分けて評価する
のはできます。
でも、その結果だけで
「適切なKは絶対に3です」
と断言するのは危ないです。
そこでよく使う方法
少ないデータでは、交差検証の考え方が向いています。
例: 5分割交差検証
40人を 5つに分けて、毎回
- 32人で訓練
- 8人でテスト
を行います。
これを5回くり返して、全員が1回ずつテストに回るようにします。
そして各 K について平均を比べます。
たとえば、
- K=1 → 平均正解率 70%
- K=3 → 平均正解率 80%
- K=5 → 平均正解率 77%
のように見ます。
こうすると、たまたまの分け方の運を減らせます。
なぜ交差検証がよいのか
1回だけの 30/10 分割だと、評価はその10人だけで決まります。
でも交差検証なら、
- いろいろな分け方で試す
- 複数回の結果を平均する
ので、より公平です。
少ないデータほど、この方法の価値が大きいです。
今回のデータ数での現実的な見方
もし本当に40人程度なら、次のように考えるとよいです。
- 30/10 の1回分割でも練習としてはよい
- でも「最適なK」を決めるなら不安定
- できれば交差検証で平均して選ぶ
- さらに、理系・文系の人数バランスも意識する
もう1つ大事な点
K は大きすぎても小さすぎても困ります。
-
Kが小さすぎる
→ ノイズに弱い
→ たまたま近い変わった1人に引っ張られやすい -
Kが大きすぎる
→ 全体の多数派に流されやすい
→ 細かい違いを見失いやすい
だから、テストで比べて決めるのが大事なのです。
まとめ
今回のようにデータが少ないと、
- 1回だけ 30/10 に分ける方法では結果がぶれやすい
- 40人なら実行はできるが、少し不安定
- よりよい方法は 交差検証
と言えます。
短く言うと
- 40人でもできる
- でも1回の分割だけでは少し難しい
- 交差検証の方が向いている
12. まとめ
今回の文理選択モデルでは、
- K を 1 にするか
- K を 3 にするか
- K を 5 にするか
によって、同じ人の点数でも予測結果が変わることがあります。
それを通して、
「KNN は、近いデータを何人分見るかで判断が変わる方法なんだ」
と理解できれば、原理の大切な部分をしっかりつかめています。
その理解の中心
KNN の考え方は、とても簡単に言うと
- 新しい人に近い人を探す
- その近い人たちの多数決で決める
です。
だから K の値が変わると、
- 参考にする人数が変わる
- 多数決の結果も変わる
- 予測も変わる
という流れになります。
これはまさに KNN の本質です。
今回の例で分かること
たとえば、
- K=1 なら、いちばん近い 1人だけを見る
- K=3 なら、近い 3人を見る
- K=5 なら、近い 5人を見る
ので、
- 近くにいる 1人の影響を強く受ける場合もある
- 少し広く周りを見ると結果が変わる場合もある
ということが見えてきます。
この「結果が変わる」という事実は、
KNN が単なる固定ルールではなく、
近傍の取り方で判断が変化するモデル
だと理解するのにとてもよい教材です。
ただし、もう一歩だけ付け加えるとよりよいです
「K によって文系にも理系にも変わる」だけでも大事な理解ですが、さらに次の点まで言えると、とてもよい理解になります。
1. K が小さいと近くの1点に影響されやすい
- ノイズ
- 外れ値
- 偶然近い1人
に引っぱられやすいです。
2. K が大きいと全体の傾向を見やすい
- 個別の細かい違いは弱まる
- 多数派に寄りやすい
です。
つまり、
K は「細かく見るか、広く見るか」の調整つまみ
のようなものだと考えると分かりやすいです。
授業での理解としては十分よいか
特に高校の学習や入門段階では、
- 距離で近さを決める
- 近いもの同士は同じ仲間と考える
- K によって結論が変わる
- だから K の選び方が大事
ここまで理解できれば、KNN の原理をかなりしっかり理解していると言えます。
先生向け・学習のまとめとして言うなら
次のように言えると、とてもよくまとまります。
KNN は、未知のデータに対して、近くにある既知データを K 個選び、その多数決で分類する方法である。したがって、K の値によって予測結果が変わることがあり、K の設定は分類結果に大きく影響する。
この言い方ができれば、原理理解としてかなり良いです。
ひとことでまとめると
「K の値によって文系にも理系にも変わることがある」と理解するのは、KNN の原理を理解するうえで非常に大切で、よい理解です。
さらに、
「なぜ変わるのか=近くの何人を多数決に使うかが変わるから」
まで言えれば、より完璧です。
追記: 記事のデータをエクセルの散布図で表せるようにcsvにしてください。理系と文系を色違いでプロットするにはどうしますか。また自分も色違いでプロットできますか。
まず、Excelで散布図にしやすいように、理系 と 文系 と 自分 を列で分けた CSV 形式にします。
以下をそのまま scores.csv などの名前で保存してください。
名前,数学_理系,国語_理系,数学_文系,国語_文系,数学_自分,国語_自分
A先輩,80,40,, ,,
B先輩,75,55,, ,,
C先輩,70,50,, ,,
D先輩,,,40,80,,
E先輩,,,30,75,,
F先輩,,,50,70,,
G先輩,,,63,62,,
自分,,,,,65,60
ただし、Excelでは空欄に余計な空白があると扱いにくいことがあるので、より安全なのは次の形です。
名前,数学_理系,国語_理系,数学_文系,国語_文系,数学_自分,国語_自分
A先輩,80,40,,,,
B先輩,75,55,,,,
C先輩,70,50,,,,
D先輩,,,40,80,,
E先輩,,,30,75,,
F先輩,,,50,70,,
G先輩,,,63,62,,
自分,,,,,65,60
Excelで理系と文系を色違いでプロットする方法
- 上のCSVをExcelで開きます
-
数学_理系と国語_理系の2列を使って散布図を作ります - グラフを右クリックして「データの選択」を開きます
- 「追加」を押して、文系の系列を追加します
- 系列名: 文系
- Xの値:
数学_文系の列 - Yの値:
国語_文系の列
- 同じように「自分」も追加できます
- 系列名: 自分
- Xの値:
数学_自分 - Yの値:
国語_自分
- それぞれの系列の色を変更します
- 理系: 青
- 文系: 赤
- 自分: 緑
のようにすると見やすいです。
なぜこの形にするのか
Excelの散布図では、1つの系列ごとに
- X座標の列
- Y座標の列
を指定します。
そのため、理系用の列、文系用の列、自分用の列 を分けておくと、色分けがとても簡単です。
自分も色違いでプロットできるか
はい、できます。
むしろ 自分 を別系列にすると、好きな色やマーカーにできます。
たとえば、
- 理系: オレンジ色の丸
- 文系: 黄色の丸
- 自分: 緑色の丸
のようにすると、どこに位置しているか一目で分かります。
「PythonでこのCSVを書き出すコード」
import csv
rows = [
["名前", "数学_理系", "国語_理系", "数学_文系", "国語_文系", "数学_自分", "国語_自分"],
["A先輩", 80, 40, "", "", "", ""],
["B先輩", 75, 55, "", "", "", ""],
["C先輩", 70, 50, "", "", "", ""],
["D先輩", "", "", 40, 80, "", ""],
["E先輩", "", "", 30, 75, "", ""],
["F先輩", "", "", 50, 70, "", ""],
["G先輩", "", "", 63, 62, "", ""],
["自分", "", "", "", "", 65, 60],
]
with open("scores.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerows(rows)
print("scores.csv を書き出しました。")
📄 ライセンスと「オープンソース」の文化について
ソースコード
本記事で紹介しているソースコードは、MIT License で公開しています。
著作権表示とライセンス表示を残すことを条件に、利用・改変・再配布などを自由に行うことができます。
学校の授業や課題、自分のプログラムや作品などにも、ぜひ活用してください。
記事本文・教材
本記事の文章・図表などの教材コンテンツは、 Creative Commons 表示 4.0 国際(CC BY 4.0) で公開しています。
授業での利用、印刷・配布、改変、翻案、再配布など、教育や学習の目的に限らず自由に利用できます。
利用する場合は、作者名・記事名・ライセンスなど、適切なクレジットを表示してください。
高校の授業で先生が必要な部分だけを抜き出したり、学校の環境に合わせて説明を書き換えたり、生徒のみなさんが自分の学習用に改造したりすることも歓迎します。
「読んで終わり」ではなく、「使って、変えて、試してみる」。
それもオープンな技術文化の一つだと考えています。
⚠️ 免責事項
本記事およびサンプルコードは、個人による学習・検証・教材作成を目的として提供しています。
コードおよび教材は現状有姿(AS IS)で提供され、利用によって生じたいかなる損害についても、執筆者は責任を負いません。
学校や組織で利用する場合は、それぞれの環境・規則・授業方針などをご確認ください。
📚 参考資料
本記事の内容をさらに学びたい方のために、参考資料・公式ドキュメント・関連する研究資料などを掲載しています。
ありがとうございます。


