グラフと定義域の検証|関数・指数・対数・総和

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

関数・指数・対数・総和(中級・読む25分+演習35分)

この授業のゴール

仕事でどう使うか

式やコードを「書けた」ことと「正しい範囲で使える」ことは別です。入力が定義域の外に出ると、エラーになるか、気づかないまま nan や inf が混ざります。

路線 この授業の使いどころ
DS(データサイエンティスト) 対数変換の前に0や負の値を確認する。報告グラフの軸(線形か対数か)を選び、読み手が誤解しないようにする
ML(機械学習エンジニア) 対数損失で予測確率が0や1にならないよう制限(クリッピング)する。学習が突然 nan になる原因を調べる
DX(DX推進・AI企画) 試算モデルの入力範囲(利率・期間・件数)を仕様書に書く。範囲外の入力に対する扱いを決める
RS(研究者) 対数尤度の最大値の位置を図で確認する。対数軸で指数則を検証し、外挿(範囲外の予測)の危うさを説明する

実務では「この式はどの範囲で正しいか」「その前提が満たされているか」を答えられることが、計算力と同じくらい求められます。

前提

この授業はMA01のまとめです。次の内容を使います。

コードは画面内のPythonで実行します。図は plt.show() を書かなくても表示されます。

身近な状況:コイン投げ5回で3回表だった

ある新機能のボタンを5回表示したところ、3回クリックされました(クリックを「表」と呼びます)。真のクリック確率 $p$ はいくつだと考えるのがもっともらしいでしょうか。

$p$ の候補ごとに、「5回中3回クリック」というデータがどれだけ起こりやすいかを計算します。1回ごとの結果は独立と仮定します。

$p=0.6$ のほうが、データを説明する力が少し高いことがわかります。この「データが出る確率」を $p$ の関数として見たものを尤度(ゆうど、likelihood)と呼びます。確率の積が小さくなりやすいので、対数をとった対数尤度で扱います。この授業では、指数・対数・総和・定義域を総動員して、この小さな例を完全に検証します。

直感的な説明:グラフは「入力を動かして出力を見る」装置

グラフは、入力 $x$ を左から右に動かしたときの出力 $y$ を、点でつないだ絵です。読むときの確認は3点です。

  1. どの範囲の $x$ を描いたか(定義域のうち、どこまで見ているか)
  2. どの軸が線形で、どの軸が対数か(目盛りの等間隔が、足し算か掛け算か)
  3. 範囲外ではどうなるか(外挿の危うさ)

対数軸では、目盛りが10倍ずつ(1, 10, 100, …)等間隔に並びます。指数的に増える量 $y=A\,r^x$ は、$\ln y=\ln A+x\ln r$ と $x$ について直線なので、縦軸を対数にすると直線に見えます。傾きが成長率に対応します。

正確な定義:定義域の検証手順と対数尤度

定義域の検証手順(式を使う前に毎回):

  1. 式に出てくる割り算(分母が0でない)
  2. 平方根(中身が0以上)
  3. 対数(真数が正、底は正で1でない)
  4. 指数(底が正)
  5. 実世界の制約(確率は0〜1、個数は0以上の整数、率が−1より大きい)

ベルヌーイ試行の対数尤度:1回ごとに確率 $p$ で成功(1)、確率 $1-p$ で失敗(0)とします。$n$ 回のうち $k$ 回成功のとき、尤度と対数尤度は

$$L(p)=p^{k}(1-p)^{n-k},\qquad \ell(p)=\ln L(p)=k\ln p+(n-k)\ln(1-p)$$

$n$ は試行回数、$k$ は成功回数、$p$ は成功確率で定義域は $0<p<1$ です($p=0$ や $1$ では $\ln p$ や $\ln(1-p)$ が定義できません)。$\ln$ は自然対数です(対数と桁)。

数値代入:$n=5,\ k=3,\ p=0.6$ のとき

$\ell(0.6)=3\ln0.6+2\ln0.4=3(-0.5108)+2(-0.9163)=-1.5325-1.8326=-3.3651$。

確認:$\ln L(0.6)=\ln0.03456=-3.3651$ と一致します。$p=0.5$ では $\ell(0.5)=5\ln0.5=-3.4657$ で、$p=0.6$ のほうが大きい(0に近い)ので、データをよりよく説明します。

注意:対数尤度は負の数です。「負の値だから悪い」のではなく、大きいほど(0に近いほど)よいと読みます。比較は同じデータ・同じ底で行います。

import math

def loglik(p, n, k):
    # p: 成功確率 (0<p<1)  n: 試行回数  k: 成功回数  戻り値: 対数尤度 (float)
    if not (0 < p < 1):
        raise ValueError("p は 0 より大きく 1 より小さい値にしてください: " + str(p))
    return k * math.log(p) + (n - k) * math.log(1 - p)

for p in [0.3, 0.5, 0.6, 0.7]:
    print(p, round(loglik(p, 5, 3), 4))

出力は p=0.3 で約−4.3253、0.5 で−3.4657、0.6 で−3.3651、0.7 で約−3.478です。0.6付近が最大に近いことがわかります。

段階付き例題:複利と対数尤度を同じ手順で検証する

例題A:複利。100万円を年3%の複利で10年運用する。

例題B:対数尤度。$n=10$ 回中 $k=4$ 回成功、$p=0.4$ と $0.5$ を比較。

import math
print(round(100 * 1.03 ** 10, 2), round(100 * (1 + 0.03 * 10), 2))
print(round(math.log(2) / math.log(1.03), 2))
def loglik(p, n, k):
    return k * math.log(p) + (n - k) * math.log(1 - p)
print(round(loglik(0.4, 10, 4), 4), round(loglik(0.5, 10, 4), 4))

出力は 134.39 と 130.0、23.45、−6.7301 と −6.9315 です。

操作して理解する:グラフで確かめ、範囲外を入れてみる

まず、指数と線形を線形軸と対数軸で並べます。

import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 31)
exp_y = 100 * 1.1 ** x
lin_y = 100 + 10 * x
fig, ax = plt.subplots(1, 2, figsize=(9, 3.5))
for a, log in zip(ax, [False, True]):
    a.plot(x, exp_y, label="指数 1.1倍/期")
    a.plot(x, lin_y, label="線形 +10/期")
    if log:
        a.set_yscale("log")
    a.set_title("縦軸 " + ("対数" if log else "線形"))
    a.set_xlabel("period")
    a.legend()

左(線形軸)では指数がカーブを描き、右(対数軸)では指数が直線、線形がゆるやかなカーブになります。軸の種類が違えば、同じデータでも見え方が違うことに注意します。

次に、対数尤度を $p$ の関数として描き、範囲を確認します。

import numpy as np
import matplotlib.pyplot as plt
n, k = 5, 3
p = np.linspace(0.01, 0.99, 99)
ll = k * np.log(p) + (n - k) * np.log(1 - p)
plt.plot(p, ll)
plt.axvline(k / n, linestyle="--")
plt.xlabel("p (0<p<1)")
plt.ylabel("log-likelihood")
print("最大の p:", round(float(p[np.argmax(ll)]), 2))

出力の 最大の p: 0.6 は、$k/n=3/5$ と一致します。端の $p\to0$、$p\to1$ では値が急激に小さく(絶対値が大きく)なります。p を np.linspace(0, 1, 101) に変えて0と1を含めるとどうなるかも試してみましょう。0と1で -inf が出て、argmax や平均が壊れます。

発展:外挿の危うさと数値的な安定性

外挿(観測した範囲の外を予測すること)は、モデルの形が範囲外でも成り立つと仮定する行為です。月次成長率10%を観測した3か月のデータから、5年後の値を指数で予測しても、市場の限界やデータの偏りを無視しています。予測には必ず前提と範囲を書きます。

数値的な安定性:np.log(0) は -inf になります。確率が0に近いときは np.clip(p, 1e-12, 1-1e-12) のように範囲を制限する実装がよく使われます。これは「定義域に入れる」操作ですが、人工的に値を変えるので、制限した件数を記録します。

最尤推定(尤度を最大にする $p$ を選ぶ方法)では、$\ell(p)$ を $p$ で微分して0とおくと $\hat p=k/n$ を得ます。微分は「極限と連続の直感と定義」(有料版)以降で学びます。ここでは図で最大位置が $k/n$ であることを確認すれば十分です。ただし、データが少ない($n=5$)ときは $\hat p$ の不確かさが大きいことに注意します(区間推定は統計モジュールで扱います)。

よくある失敗

失敗1:p=0 や p=1 を対数尤度に入れる

import numpy as np
n, k = 5, 3
for p in [0.0, 0.6, 1.0]:
    with np.errstate(divide="ignore", invalid="ignore"):
        print(p, k * np.log(p) + (n - k) * np.log(1 - p))

$p=0$ や $p=1$ では -inf(または nan)になります。$k=3$ のデータで $p=0$ とは「成功が一度も起きない」という主張で、データと矛盾します。直し方:$p$ の範囲を $0<p<1$ に限り、範囲外は例外にするか、理由を記録したうえで制限する。

失敗2:対数軸のグラフで0や負の値を描こうとする

import numpy as np
y = np.array([100.0, 10.0, 0.0, -5.0])
with np.errstate(divide="ignore", invalid="ignore"):
    print(np.log10(y))

0は -inf、−5は nan で、対数軸には描けません(描画ソフトはこれらの点を黙って省略することがあります)。直し方:対数軸を使う前に、最小値が正かどうか確認する。省略された点があれば、その件数を注記する。

失敗3:外挿した直線・曲線を事実のように報告する

import numpy as np
t = np.arange(1, 7)
y = 100 * 1.1 ** t
b = np.polyfit(t, np.log(y), 1)
pred = np.exp(np.polyval(b, 60))
print("60期後の予測:", round(float(pred), 1))

6期分のデータから60期後を予測すると約30,448という巨大な値が出ますが、市場の上限などの制約を考慮していません。直し方:予測の範囲と前提(成長が続く期間)を明記し、複数のシナリオ(楽観・標準・悲観)を示す。

まとめ

用語

尤度・対数尤度(likelihood / log-likelihood)

データを固定してパラメータの関数として見た、そのデータの起こりやすさ。対数尤度はその自然対数。

外挿(extrapolation)

観測した範囲の外を予測すること。

対数軸(log scale)

目盛りが10倍や2倍ごとに等間隔に並ぶ軸。

よくある質問

なぜグラフを描く前に定義域を確認するのですか?

範囲外の入力は、エラーで止まるより nan や -inf として静かに混ざるほうが危険だからです。事前の確認で、集計や図の異常の原因を絞れます。

対数軸と線形軸はどう使い分けますか?

桁が大きく異なるデータや、成長率の一定性を見たいときは対数軸、絶対的な増加量を見せたいときは線形軸です。読み手に伝わるように、軸の種類を図に明記します。

尤度と確率の違いは?

確率はパラメータを固定してデータの起こりやすさを言い、尤度はデータを固定してパラメータの「もっともらしさ」を $p$ の関数として見ます。尤度は $p$ について足して1になる量ではありません。

対数尤度が負なのは問題ですか?

問題ありません。尤度が1以下なので、対数は0以下になります。比較には、大きいほど(0に近いほど)よいと読みます。

複利と対数尤度は何のつながりがありますか?

どちらも「掛け算を対数で足し算に変えて扱う」点が共通です。複利の倍増期間は $\ln2/\ln(1+r)$、対数尤度は確率の積の対数です。定義域($1+r>0$、$0<p<1$)を確認する手順も同じです。

実務で `nan` が出たらどう調べますか?

対数・割り算・平方根の入力を順に出力して、0や負の値が入っていないかを確認します。見つけたら、その行の意味(本当に0か、欠損か)を確認してから処理方法を決めます。

確認問題

問1 対数尤度 $\ell(p)=k\ln p+(n-k)\ln(1-p)$ が定義できる $p$ の範囲は。

  1. ① $0\le p\le1$
  2. ② $0<p<1$
  3. ③ $p>0$
  4. ④ 任意の実数
解答と解説

正解:②

$\ln p$ と $\ln(1-p)$ の両方で真数が正である必要があるので、$0<p<1$ です。

問2 縦軸を対数にしたとき、毎期一定の割合で増える量はどう見えるか。

  1. ① 曲線
  2. ② 直線
  3. ③ 水平線
  4. ④ 階段状
解答と解説

正解:②

$\ln y=\ln A+x\ln r$ は $x$ の1次式なので直線です。傾きが成長率に対応します。

問3 対数尤度が−3.37と−3.47のとき、データをよく説明するのは。

  1. ① どちらも同じ
  2. ② 符号が負なので比較できない
  3. ③ −3.47(絶対値が大きいほうがよい)
  4. ④ −3.37(0に近いほうがよい)
解答と解説

正解:④

対数は単調増加なので、対数尤度が大きい(0に近い)ほうが尤度も大きくなります。

問4 np.log(0.0) の結果として正しいのは。

  1. ① 0.0
  2. ② −inf(警告が出ることがある)
  3. ③ 1.0
  4. ④ ValueError で必ず止まる
解答と解説

正解:②

numpy は -inf を返します(math.log(0) は ValueError)。後の集計に静かに紛れ込む点が危険です。

問5 100万円を年3%の複利で10年運用した金額に最も近いのは。

  1. ① 130万円
  2. ② 約134万円
  3. ③ 約1379万円
  4. ④ 約103万円
解答と解説

正解:②

$100\times1.03^{10}=134.39$ 万円。130万円は単利(線形)の見積もりです。

問6 6期分のデータから指数曲線を当てはめ、60期後を予測した値の扱いとして適切なのは。

  1. ① 前提と範囲(成長が続く期間)を明記し、シナリオ別に示す
  2. ② 対数をとったので正確とみなす
  3. ③ データ数に関係なく信頼できる
  4. ④ 事実として報告する
解答と解説

正解:①

観測範囲の外を予測する外挿は、モデルが範囲外でも成り立つ仮定を含みます。

次に学ぶこと

MA01 はこれで終わりです。総合テストと自力課題に進んでください。つまずいたら、定義域は 対数と桁、複利は 指数と増減率、Σ と Π は 総和と総乗の記号 に戻ります。先に進む次のモジュールは 集合・命題・証明の読み方(有料版)(集合・命題・証明の読み方)、微分は 微分・近似・1変数の最適化(有料版) です。

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

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

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