グラフと定義域の検証|関数・指数・対数・総和
このページはプロモーション(広告)を含みます。
関数・指数・対数・総和(中級・読む25分+演習35分)
この授業のゴール
- 関数のグラフを描き、定義域の外の入力が何を引き起こすか(エラー・nan・-inf)を確認できる
- 線形軸と対数軸のグラフを使い分け、指数的な増加を対数軸で直線として見分けられる
- 確率の小例で対数尤度を計算し、p の取りうる範囲(0
- 複利と対数尤度の計算を、手計算とコードで照合して検算できる
仕事でどう使うか
式やコードを「書けた」ことと「正しい範囲で使える」ことは別です。入力が定義域の外に出ると、エラーになるか、気づかないまま 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.5$ のとき:$0.5^3\times0.5^2=0.03125$
- $p=0.6$ のとき:$0.6^3\times0.4^2=0.216\times0.16=0.03456$
$p=0.6$ のほうが、データを説明する力が少し高いことがわかります。この「データが出る確率」を $p$ の関数として見たものを尤度(ゆうど、likelihood)と呼びます。確率の積が小さくなりやすいので、対数をとった対数尤度で扱います。この授業では、指数・対数・総和・定義域を総動員して、この小さな例を完全に検証します。
直感的な説明:グラフは「入力を動かして出力を見る」装置
グラフは、入力 $x$ を左から右に動かしたときの出力 $y$ を、点でつないだ絵です。読むときの確認は3点です。
- どの範囲の $x$ を描いたか(定義域のうち、どこまで見ているか)
- どの軸が線形で、どの軸が対数か(目盛りの等間隔が、足し算か掛け算か)
- 範囲外ではどうなるか(外挿の危うさ)
対数軸では、目盛りが10倍ずつ(1, 10, 100, …)等間隔に並びます。指数的に増える量 $y=A\,r^x$ は、$\ln y=\ln A+x\ln r$ と $x$ について直線なので、縦軸を対数にすると直線に見えます。傾きが成長率に対応します。
正確な定義:定義域の検証手順と対数尤度
定義域の検証手順(式を使う前に毎回):
- 式に出てくる割り算(分母が0でない)
- 平方根(中身が0以上)
- 対数(真数が正、底は正で1でない)
- 指数(底が正)
- 実世界の制約(確率は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年運用する。
- ステップ1:定義域。倍率 $1+r=1.03>0$、年数 $n=10$(整数)。範囲は問題ない。
- ステップ2:$100\times1.03^{10}=100\times1.343916=134.39$ 万円。
- ステップ3:検算。線形の見積もり $100\times(1+0.03\times10)=130$ 万円と比較し、指数のほうが大きいことを確認。
- ステップ4:倍増期間 $\ln2/\ln1.03\approx23.45$ 年。
例題B:対数尤度。$n=10$ 回中 $k=4$ 回成功、$p=0.4$ と $0.5$ を比較。
- ステップ1:定義域 $0<p<1$ を確認。
- ステップ2:$\ell(0.4)=4\ln0.4+6\ln0.6=4(-0.9163)+6(-0.5108)=-6.7301$。
- ステップ3:$\ell(0.5)=10\ln0.5=-6.9315$。
- ステップ4:$\ell(0.4)>\ell(0.5)$ なので、$p=0.4$(成功の割合 $k/n$)のほうがデータをよく説明する。差は約0.2014。
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という巨大な値が出ますが、市場の上限などの制約を考慮していません。直し方:予測の範囲と前提(成長が続く期間)を明記し、複数のシナリオ(楽観・標準・悲観)を示す。
まとめ
- 式を使う前に、割り算・平方根・対数・指数・実世界の制約という5点で定義域を確認する。
- 対数尤度 ℓ(p)=k ln p+(n−k) ln(1−p) の定義域は 0
- 縦軸を対数にすると、一定の成長率の量は直線に見える。軸の種類は図に明記する。
- 外挿は前提と範囲を書く。0や負の対数は nan/-inf として静かに混ざるので事前に検証する。
用語
- 尤度・対数尤度(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$ の範囲は。
- ① $0\le p\le1$
- ② $0<p<1$
- ③ $p>0$
- ④ 任意の実数
解答と解説
正解:②
$\ln p$ と $\ln(1-p)$ の両方で真数が正である必要があるので、$0<p<1$ です。
問2 縦軸を対数にしたとき、毎期一定の割合で増える量はどう見えるか。
- ① 曲線
- ② 直線
- ③ 水平線
- ④ 階段状
解答と解説
正解:②
$\ln y=\ln A+x\ln r$ は $x$ の1次式なので直線です。傾きが成長率に対応します。
問3 対数尤度が−3.37と−3.47のとき、データをよく説明するのは。
- ① どちらも同じ
- ② 符号が負なので比較できない
- ③ −3.47(絶対値が大きいほうがよい)
- ④ −3.37(0に近いほうがよい)
解答と解説
正解:④
対数は単調増加なので、対数尤度が大きい(0に近い)ほうが尤度も大きくなります。
問4 np.log(0.0) の結果として正しいのは。
- ① 0.0
- ② −inf(警告が出ることがある)
- ③ 1.0
- ④ ValueError で必ず止まる
解答と解説
正解:②
numpy は -inf を返します(math.log(0) は ValueError)。後の集計に静かに紛れ込む点が危険です。
問5 100万円を年3%の複利で10年運用した金額に最も近いのは。
- ① 130万円
- ② 約134万円
- ③ 約1379万円
- ④ 約103万円
解答と解説
正解:②
$100\times1.03^{10}=134.39$ 万円。130万円は単利(線形)の見積もりです。
問6 6期分のデータから指数曲線を当てはめ、60期後を予測した値の扱いとして適切なのは。
- ① 前提と範囲(成長が続く期間)を明記し、シナリオ別に示す
- ② 対数をとったので正確とみなす
- ③ データ数に関係なく信頼できる
- ④ 事実として報告する
解答と解説
正解:①
観測範囲の外を予測する外挿は、モデルが範囲外でも成り立つ仮定を含みます。
次に学ぶこと
MA01 はこれで終わりです。総合テストと自力課題に進んでください。つまずいたら、定義域は 対数と桁、複利は 指数と増減率、Σ と Π は 総和と総乗の記号 に戻ります。先に進む次のモジュールは 集合・命題・証明の読み方(有料版)(集合・命題・証明の読み方)、微分は 微分・近似・1変数の最適化(有料版) です。
この授業の確認問題だけで習得とはしません。MA01 の総合テストと別条件の自力課題で判定します。
キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。
アプリを無料で開く有料版と無料版の違い