MLの仕事を小例で体験|データ・AI・4つの仕事を知る

このページはプロモーション(広告)を含みます。

データ・AI・4つの仕事を知る(初級・読む20分+演習30分)

この授業のゴール

仕事でどう使うか

機械学習(ML)エンジニアの仕事は、モデルを作ることに限りません。予測を業務で使い続けられる仕組みにすることが中心です。データの取得、予測の実行、現場への提示、誤りの監視、失敗したときの代替手順までが対象になります。

路線 この授業の使いどころ
DS(データサイエンティスト) 予測の前に、何が基準になるかを分析で示す。予測誤差と事業上の損失を並べて報告する
ML(機械学習エンジニア) 予測の入力・評価期間・基準を定義し、運用できる形(定期実行・監視・代替手順)にする
DX(DX推進・AI企画) 予測を使う業務手順(誰が見て、誰が発注を決めるか)を設計し、例外を処理する
RS(研究者) 予測法の比較条件(同じデータ、同じ分割、同じ指標)をそろえる

担当は職場により異なります。肩書でなく成果物(予測の仕様書・評価結果・運用手順)で確認してください。

前提

Pythonのリスト([1, 2, 3] のように値を並べた型)と、スライス(a[2:5] で添字2以上5未満の要素を取り出す書き方。添字は0から数える)を使います。

身近な状況:「来週の仕入れ量を決めたい」

雑貨店「ことり堂」(架空)で、人気商品Aの仕入れ量を、毎週金曜に翌週ぶんを決めています。仕入れが少なければ売り逃し(欠品)、多ければ売れ残り(廃棄や値引き)になります。店長は言います。「AIで来週の販売個数を当てられない?」

手元にあるのは、12週間の販売個数と来店者数です(架空のデータ)。

週 1 2 3 4 5 6 7 8 9 10 11 12
販売個数(個) 100 104 98 110 108 115 112 120 118 125 122 130
来店者数(人) 500 520 490 550 540 575 560 600 590 625 610 650

MLエンジニアは、いきなりモデルを選ばず、次の4点を確認します。

  1. 何を当てるのか(目的変数):翌週の販売個数(個)。
  2. いつ予測するのか:毎週金曜に、翌週1週間ぶんを予測する。
  3. その時点で使える入力は何か:金曜までの販売個数、来店者数、曜日の情報。翌週の来店者数は金曜には分からない。
  4. どう評価するのか:予測を作った後に観測された週での誤差と、欠品・廃棄の損失。

この4点が曖昧だと、「使えない予測」になります。

直感的な説明:過去で練習し、未来で試す

予測の良し悪しは、予測を作る時点では見えなかった期間で測ります。試験にたとえると分かりやすいです。

練習問題と本番が同じ問題なら、満点が取れます。同じように、学習期間のデータで誤差を測ると、実際より良く見えます。

時間のあるデータでは順番も重要です。第5週を予測するのに第6週以降のデータを使ってはいけません。運用では未来のデータは存在しないからです。

もう1つ重要なのは、複雑な方法の前に、単純な基準を測ることです。「前の週と同じ個数にする」だけで十分当たることがあります。基準より良くならない方法は、運用の手間をかける価値がありません。

正確な定義:時間順の分割・ベースライン・漏洩

用語を定義します。

評価には、L02で学んだ平均絶対誤差 $\text{MAE} = \frac{1}{n}\sum |y_i - \hat{y}_i|$ を使います。$y_i$ は実績(個)、$\hat{y}_i$ は予測(個)、$n$ は評価した週の数です。

評価期間(第9〜12週)の実績は $(118, 125, 122, 130)$ です。

方法Nの予測は、各週の前週の実績で、$(120, 118, 125, 122)$。誤差は $2, 7, 3, 8$ で、合計20、MAE は $20 \div 4 = 5.0$ 個です。

方法Mの予測は、第9週が $(108+115+112+120)/4 = 113.75$、第10週が $(115+112+120+118)/4 = 116.25$、第11週が $(112+120+118+125)/4 = 118.75$、第12週が $(120+118+125+122)/4 = 121.25$。誤差は $4.25, 8.75, 3.25, 8.75$ で、合計25、MAEは $25 \div 4 = 6.25$ 個です。

この期間では、「前週と同じ」のほうが4週移動平均より誤差が小さいです。右肩上がりのため、過去の平均は低めになるからです。

段階付き例題:基準を測り、費用で評価し、漏洩を見つける

ステップ1:基準の誤差を測る。次のコードで、2つの方法のMAEを計算します。sales[i-4:i] は、第 $i$ 番目(0から数える)の直前4週を取り出すスライスです。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
test = sales[8:]                                   # 評価期間(第9〜12週)

def mae(actual, pred):
    return sum(abs(a - p) for a, p in zip(actual, pred)) / len(actual)

pred_n = [sales[i - 1] for i in range(8, 12)]               # 前週と同じ
pred_m = [sum(sales[i - 4:i]) / 4 for i in range(8, 12)]    # 直前4週の平均
print("実績", test)
print("方法N", pred_n, "MAE", mae(test, pred_n))
print("方法M", pred_m, "MAE", mae(test, pred_m))

出力は、方法Nが [120, 118, 125, 122] でMAE 5.0、方法Mが [113.75, 116.25, 118.75, 121.25] でMAE 6.25です。

ステップ2:誤差を費用で見る。仕入れでは、多すぎる(廃棄)と少なすぎる(欠品)で損失が違います。仮に、1個多いと100円、1個足りないと300円の損失(売り逃した粗利)とします(架空の仮定)。予測が実績より大きい分が「過剰」、小さい分が「不足」です。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
test = sales[8:]
def mae(actual, pred):
    return sum(abs(a - p) for a, p in zip(actual, pred)) / len(actual)
def loss(actual, pred, over_cost=100, under_cost=300):
    over = sum(max(p - a, 0) for a, p in zip(actual, pred))     # 過剰(個)
    under = sum(max(a - p, 0) for a, p in zip(actual, pred))    # 不足(個)
    return over * over_cost + under * under_cost

pred_n = [sales[i - 1] for i in range(8, 12)]
pred_n5 = [x + 5 for x in pred_n]                  # 前週と同じに5個上乗せ
print("方法N     MAE", mae(test, pred_n), "損失", loss(test, pred_n), "円")
print("方法N+5   MAE", mae(test, pred_n5), "損失", loss(test, pred_n5), "円")

出力は、方法Nが MAE 5.0・損失 5000円、方法N+5が MAE 5.0・損失 3000円です。誤差の大きさ(MAE)は同じでも、事業上の損失は違います。不足が高くつく状況では、少し多めの予測が得です。精度と事業価値は別の量です。

ステップ3:漏洩を見つける。「販売個数=来店者数の0.2倍」という関係が、この表では成り立っています。そこで、評価期間の各週について「当週の来店者数×0.2」で予測すると、どうなるでしょう。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
test = sales[8:]
pred_leak = [round(0.2 * visitors[i], 6) for i in range(8, 12)]       # 当週の来店者数を使う
pred_ok = [round(0.2 * visitors[i - 1], 6) for i in range(8, 12)]     # 前週の来店者数を使う
mae = lambda a, p: sum(abs(x - y) for x, y in zip(a, p)) / len(a)
print("当週の来店者数を使った予測", pred_leak, "MAE", mae(test, pred_leak))
print("前週の来店者数を使った予測", pred_ok, "MAE", mae(test, pred_ok))

出力は、当週の来店者数を使うとMAE 0.0、前週の来店者数を使うとMAE 5.0です。MAE 0.0は魅力的に見えますが、金曜の時点では翌週の来店者数は分かりません。これは漏洩です。運用では当週の来店者数が手に入らず、モデルは動かせません。来店者数の予測を入力に使うなら、その誤差が加わります。

操作して理解する:自分で基準を作り、評価期間を変える

次のコードで、評価期間と方法を変えて試します。評価期間を短くしたり、長くしたりして、結果を予想してください。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
def mae(actual, pred):
    return sum(abs(a - p) for a, p in zip(actual, pred)) / len(actual)

def evaluate(start):
    # start 番目(0から数える)以降を評価期間にする
    idx = range(start, len(sales))
    test = [sales[i] for i in idx]
    n = [sales[i - 1] for i in idx]
    m = [sum(sales[i - 4:i]) / 4 for i in idx]
    return round(mae(test, n), 2), round(mae(test, m), 2)

for start in (4, 6, 8, 10):
    print("評価開始", start + 1, "週目から: 方法N, 方法M =", evaluate(start))

出力は次のとおりです。

評価開始 5 週目から: 方法N, 方法M = (5.0, 6.62)
評価開始 7 週目から: 方法N, 方法M = (5.17, 6.33)
評価開始 9 週目から: 方法N, 方法M = (5.0, 6.25)
評価開始 11 週目から: 方法N, 方法M = (5.5, 6.0)

考えてみましょう。

  1. どの開始週でも、方法Nの誤差(5.0〜5.5個)が方法Mの誤差(6.0〜6.6個)より小さい。評価期間を変えても順位が変わらないので、この比較は少し信頼できます。
  2. 一方、同じ方法Nでも、評価期間によって5.0、5.17、5.0、5.5と値が動きます。12週間のうち数週間だけの評価では、小さな差を強く言えません。
  3. 方法Mの 4 を 2 に変えて、結果を確認しましょう。

運用のためには、(1)毎週金曜の午前に実行して期限内に結果を出す、(2)入力の欠損・休業日の0・極端な値を確認する、(3)予測値と前週の実績を並べて現場に示し、最終的に誰が発注数を決めるかを定める、(4)予測と実績の誤差を毎週記録し基準より悪化したら知らせる、(5)予測が出ないときは「前週と同じ」で発注する、という要素も必要です。

発展:時系列の評価とモデルの更新

評価期間を1つに固定する方法のほかに、時間を進めながら繰り返し評価する方法があります。第8週までで第9週を予測、第9週までで第10週を予測、というように評価を1週ずつ進めて誤差を集めると、4週だけの評価より結論が安定します。scikit-learn の TimeSeriesSplit は、時間順を保ったまま分割する道具です(本授業の範囲外)。

手法(線形回帰、決定木、ニューラルネットなど)は、これらの設計が固まってから選びます。基準を超えられない手法は導入しません。

よくある失敗

失敗1:学習したデータでそのまま誤差を測る

誤った評価:第1〜12週すべてを使って方法を作り、同じ第1〜12週で誤差を測る。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
# 全期間の平均値を予測として使い、同じ期間で評価する
avg = sum(sales) / len(sales)
pred_all = [avg] * len(sales)
mae = lambda a, p: sum(abs(x - y) for x, y in zip(a, p)) / len(a)
print("全期間の平均", round(avg, 2))
print("同じ期間で評価したMAE", round(mae(sales, pred_all), 2))
# 本来の評価:第8週までの平均で、第9〜12週を予測
avg8 = sum(sales[:8]) / 8
print("第8週までの平均", round(avg8, 2), "評価期間のMAE", round(mae(sales[8:], [avg8] * 4), 2))

出力は、全期間の平均 113.5、同じ期間で評価したMAE 8.17、第8週までの平均 108.38、評価期間のMAE 15.38 です。同じ期間で測ると、実際の使い方より良く見えます。

直し方:学習期間と評価期間を時間順に分け、評価期間は方法を作るときに一切使いません。

失敗2:ランダムに分けて、未来のデータを学習に使う

時系列を、普通の表のようにランダムに学習用と評価用へ分けると、評価用の週の前後のデータが学習に入ります。たとえば第9週を予測するのに第10週の値を使えてしまいます。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
# 評価用の週を第9週にして、前後の週の平均で予測する(未来の第10週を使っている)
pred_w9 = (sales[7] + sales[9]) / 2
print("第9週の実績", sales[8], "前後平均の予測", pred_w9, "誤差", abs(sales[8] - pred_w9))
# 金曜時点で使える方法:前週の値
print("前週と同じ 予測", sales[7], "誤差", abs(sales[8] - sales[7]))

出力は、前後平均の予測122.5で誤差4.5、前週と同じ予測120で誤差2です(この週では前週のほうが近いですが、未来を使う方法は運用で使えません)。運用では第10週のデータは存在しないため、未来を使った評価は実際の性能を表しません。

直し方:時系列は、学習期間を過去、評価期間を未来にして分けます。評価期間のデータは、方法を決める時点では存在しないものとして扱います。

失敗3:誤差が小さいことだけで「導入する」と決める

誤った判断:「方法NもMも誤差は数個。どちらでも十分当たっているから、複雑なAIを導入しよう。」

誤差の大きさは、事業の損失と1対1に対応しません。前の例では、方法Nは MAE 5.0 で損失5000円、方法Mは MAE 6.25 で全て不足となり損失7500円でした。上乗せを加えた方法N+5は、MAEが同じ5.0でも損失が3000円でした。

sales = [100, 104, 98, 110, 108, 115, 112, 120, 118, 125, 122, 130]   # 週ごとの販売個数(第1週〜第12週)
visitors = [500, 520, 490, 550, 540, 575, 560, 600, 590, 625, 610, 650]  # 週ごとの来店者数(人)
test = sales[8:]
pred_m = [sum(sales[i - 4:i]) / 4 for i in range(8, 12)]
over = sum(max(p - a, 0) for a, p in zip(test, pred_m))
under = sum(max(a - p, 0) for a, p in zip(test, pred_m))
print("方法M 過剰", over, "個 不足", under, "個")

出力は「方法M 過剰 0 個 不足 25.0 個」です。常に少なめに予測しているため、欠品が続いています。誤差の平均だけでは、この偏りは見えません。

直し方:誤差の大きさ(MAE)と、偏り(過剰・不足)と、業務の損失を別々に確認します。導入の判断は、基準との比較と、運用の費用を含めて行います。

まとめ

用語

目的変数(target variable)

予測で当てたい値。ここでは翌週の販売個数。

特徴量(feature)

予測に使う入力の値。過去の販売個数や来店者数など。

データ漏洩(リーク)(data leakage)

予測する時点では手に入らない情報が、入力や学習に混ざること。評価が見かけ上良くなる。

時間順分割(time-based split)

時系列データを、過去を学習期間、未来を評価期間として分ける方法。

移動平均(moving average)

直近k個の値の平均。ここでは直前4週の平均を予測値に使った。

よくある質問

機械学習エンジニアは、毎日モデルを作っているのですか?

多くの時間は、データの取得と整形、評価の設計、運用の仕組み、監視、関係者との調整に使われます。モデルの選択は、その一部です。ただし職場により分担は違います。

なぜ最初に単純な基準を測るのですか?

基準がないと、複雑な方法が良いのか分からないからです。「前週と同じ」でも十分当たる業務は多く、その場合は運用が簡単な基準のまま使うほうが、費用も失敗も少なくなります。

漏洩はどうすれば見つけられますか?

入力の1つずつについて「予測する時点で手に入るか」を確認します。また、誤差が不自然に小さい(MAE 0に近い)ときは、漏洩を疑います。データの記録される時点(後日まとめて入力される項目など)も確認します。

評価期間は何週間くらい必要ですか?

決まった数はありません。この授業の4週は、小さな例としては十分でも、結論を強く言うには短いです。季節性があるなら、1年以上を含めたいところです。評価期間が短いときは、結論を「この期間では」と限定します。

予測が外れたときは、誰の責任ですか?

予測の使い方を決めた業務の設計に含めます。誰が最終判断をするか、外れたときの代替手順、誤差を記録する担当を、導入前に決めます。モデルの作り手だけの責任にすると、運用が回りません。

AIを導入すること自体が目的になってしまうのはなぜ悪いのですか?

基準との比較や、費用・効果の見積もりが省かれ、使わないほうがよい案を捨てられなくなるからです。目的は、廃棄や欠品などの損失を減らすことで、手段は基準のままでもよいことがあります。

確認問題

問1 毎週金曜に翌週の販売個数を予測する。翌週の来店者数(実績)を入力に使うと、何が問題になるか。

  1. ① 金曜の時点では翌週の来店者数は分からず、運用で使えない(漏洩)
  2. ② 問題はない。来店者数は重要な情報だから
  3. ③ 来店者数は販売個数と無関係だから
  4. ④ 誤差が必ず大きくなる
解答と解説

正解:①

予測する時点で手に入らない情報を入力に使うと、評価では良く見えても運用で動かせません。

問2 時系列データの予測を評価するとき、適切な分け方はどれか。

  1. ① ランダムに半分ずつ分ける
  2. ② 評価期間の一部を学習に混ぜる
  3. ③ 全期間を学習にも評価にも使う
  4. ④ 過去を学習期間、未来を評価期間にして時間順に分ける
解答と解説

正解:④

運用では未来のデータは存在しないので、評価も過去から未来への順で行います。

問3 「前週と同じ」方法のMAEが5.0個、4週移動平均のMAEが6.25個だった。ここから言えることはどれか。

  1. ① 移動平均は常に悪い
  2. ② この評価期間では、前週と同じ方法のほうが誤差が小さい
  3. ③ 移動平均は導入してはいけない
  4. ④ 前週と同じ方法は最適である
解答と解説

正解:②

評価期間と条件の中での比較結果です。傾向が右肩上がりなので、平均が低めに出ています。

問4 予測Aと予測BはどちらもMAEが5個。Aは常に5個多め、Bは常に5個少なめ(極端な例)に外れている。欠品が高くつく場合、より問題になりやすいのはどちらか。

  1. ① A
  2. ② 同じ
  3. ③ B
  4. ④ 判断できない
解答と解説

正解:③

MAEが同じでも、偏りの向きで損失が違います。不足(欠品)が高くつくなら、少なめに偏るBが不利です。

問5 複雑な機械学習モデルを導入する前に、最初にすべきことはどれか。

  1. ① 最新のモデルを選ぶ
  2. ② 予測を使わない
  3. ③ データを増やす
  4. ④ 前週と同じなどの単純な基準の誤差を、同じ評価期間で測る
解答と解説

正解:④

基準を測らないと、モデルが改善しているかが分かりません。

問6 売り切れた日の販売個数を、そのまま「需要」として学習に使うと、どんな問題が起きるか。

  1. ① 実際の需要より少ない値を学習し、少なめの予測が続いて欠品が増える恐れがある
  2. ② 問題は起きない
  3. ③ 必ず多めの予測になる
  4. ④ データが増えるので精度が上がる
解答と解説

正解:①

売り切れた日の販売個数は、売れた数であって、欲しかった数(需要)の下限にすぎません。

次に学ぶこと

次は DXの仕事を小例で体験 で、DX(業務と組織を変える仕事)を、在庫補充の承認手順の小例で体験します。予測を作っても、承認手順が遅ければ価値は出ません。予測の評価の基礎に戻るなら 分析と予測と生成の違い を、割合の計算は 比率・割合・パーセントポイント を見直してください。

この授業の確認問題だけで習得とはしません。ON03 の総合テストと、自力課題で判定します。

キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。

アプリを無料で開く有料版と無料版の違い