ロジスティック回帰
データセットとソースファイルは、Github プロジェクト
リンクから入手できます: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-宿題
1. シグモイド分類と二項分類
線形回帰とは異なり、ロジスティック回帰は回帰と呼ばれますが、分類関数の実装によく使用されます。線形回帰との唯一の違いは、線形回帰の出力の後にシグモイド関数が追加され、その出力が値を予測せずに分類の確率を表すことができることです。シグモイド関数がなぜこのような機能を持つのかについては、次に説明します。
シグモイド関数
シグモイド関数の数式は次のとおりです。
σ ( x ) = 1 1 + e − x \sigma(x)=\frac{1}{1+e^{-x}}σ ( x )=1+e− ×1
分析により、シグモイド関数が増加関数であることがわかります。x の値が大きいほど、σ ( x ) \sigma(x)σ ( x )が 1 に近づくほど、x の値は小さくなります。σ ( x ) \sigma(x)σ ( x )は0 に近づきます。x=0 の場合、σ ( x ) = 0.5 \sigma(x)=0.5σ ( x )=0.5。その関数曲線は次のとおりです。
なぜシグモイド関数は二項分類確率を表すことができるのでしょうか?
ここで最初にベルヌーイ分布の知識を復習します。
ベルヌーイ分布は確率変数XXを指しますXが持つ、パラメータはp (0 < p < 1) p(0<p<1)p ( 0<p<1 ) 、それぞれ確率ppの場合pと1 − p 1-p1−p は値 1 と 0 をとります。E (X) = p E(X) = p元)_ _=p ,D ( X ) = p ( 1 − p ) D(X)=p(1-p)D ( X )=p ( 1−p )。成功したベルヌーイ試行の数はベルヌーイ分布、パラメーターpppは実験の成功確率です。ベルヌーイ分布は離散確率分布であり、N = 1 N=1N=1.二項分布の特殊なケース
ベルヌーイ分布の場合、p = μ x ( 1 − μ ) ( 1 − x ) p=\mu^{x}(1-\mu)^{(1-x)}p=メートル× (1−メートル)( 1 − x ),对等式為電影,有
p = ex ln μ + ( 1 − x ) ln ( 1 − μ ) = ex ln μ 1 − μ + ln ( 1 − μ ) p= e^{x\ln{\mu}+(1-x)\ln{(1-\mu)}}=e^{x\ln{\frac{\mu}{1-\mu}}+\ ln{(1-\in)}}p=eバツln _m + ( 1 − x )ln _( 1 − μ )=eバツln _1 −メートルメートル+ ln _( 1 − μ )
次に、指数分布族分布をベルヌーイ分布を表します。
指数分布族とも呼ばれる指数分布族は、統計において最も重要なパラメーター分布族です。
指数関数族分布の一般的なパラメータ化は次のように表されます:
p ( y ; η ) = b ( y ) e η ⊤ T ( y ) − α ( η ) p(y;\eta)=b(y)e^{ \eta ^{\top}T(y)-\alpha(\eta)}p ( y ;) _=さよなら_ _ _ _の⊤ T(y)−α(η)
のうち、
- やあyは自然パラメータです
- T ( y ) T(y)T ( y )はyyyの十分な統計
- α ( η ) \alpha(\eta)α ( η )は対数部関数であり、∑ p ( y ; η ) = 1 \sum{p(y;\eta)}=1 である∑p ( y ;) _=1
この式から、 η = ln μ 1 − μ \eta=\ln{\frac{\mu}{1-\mu}} が得られます。の=ln1 −メートルメートル,つまり
μ = 1 1 + e − η \mu=\frac{1}{1+e^{-\eta}}メートル=1+e−時間1
シグモイド関数はベルヌーイ分布の確率を表現できることがわかります。
2. 物流回帰
線形回帰と同様に、ロジスティック回帰も勾配ベースの最適化手法を使用して解くことができます。ロジスティック回帰のモデル式は次のとおりです:
h ( x ; θ ) = σ ( θ x ⊤ ) h(\boldsymbol{x};\boldsymbol{\theta})=\sigma{(\boldsymbol{\theta x^) { \上}})}h ( x ;私)=σ ( θ x⊤ )
ここで、x \boldsymbol{x}xは( n , d + 1 ) (n,d+1)の次元です。( n 、d+1 )サンプル (オフセット項の計算を容易にするために、最初の次元がすべて 1 になるように追加されます)、θ \boldsymbol{\theta}θは( 1 , d + 1 ) (1,d+1)です( 1 、d+1 )パラメータ。Get( 1 , n ) (1,n)( 1 、n )出力。
クロスエントロピー損失関数
線形回帰では、平均二乗誤差 MSE を使用して予測値と真の値の差を測定することができ、この数値の差に基づく損失関数は理解しやすいです。ただし、分類タスクでは、MSE は分類差の測定には明らかに適していないため、新しい損失関数とクロス エントロピー損失を導入します。
クロスエントロピー損失を理解するために、まず情報理論における重要な概念であるKL 発散から始めます。
分類タスクでは、多分類であろうと二分類であろうと、私たちのタスクは予測分布を出力するものとして見ることができます。二項分類の場合、これはベルヌーイ分布であり、多クラス分類の場合、これは多項分布です。分類効果が優れているほど、出力分布はターゲット分布に近づくはずです。では、2 つの分布の類似性をどのように測定するのでしょうか? これが KL ダイバージェンスが行うことです。
KKを考えてみましょうKクラスの分類問題。ターゲット分布をq ( k ∣ x ) q(k|x)q ( k ∣ x )、出力分布はp ( k ∣ x ) p(k|x)p ( k | x )。これら 2 つの分布はそれぞれ、サンプルがk 番目kクラスの確率。ターゲットの分布については、これがワンホット スタイルの分布であることは明らかです。つまり、真のカテゴリの確率は 1 で、その他の確率は 0 です。2 つの分布の KL 発散は次のように記述されます。
KL ( q ∣ ∣ p ) = ∑ k = 1 K q ( k ∣ x ) log q ( k ∣ x ) p ( k ∣ x ) KL(q||p )= \sum_{k=1}^{K}{q(k|x)\log{\frac{q(k|x)}{p(k|x)}}}K L ( q ∣∣ p )=k = 1∑Kq ( k ∣ x )ログ_p ( k ∣ x )q ( k ∣ x )
2 つの分布が近いほど、KL 発散は小さくなります。p = qp=qの場合、次のことが観察できます。p=qの場合、KL 発散は 0 です。
KL 発散をさらに拡張すると、次のようになります。
KL ( q ∣ ∣ p ) = ∑ k = 1 K q ( k ∣ x ) log q ( k ∣ x ) − q ( k ∣ x ) log p ( k ∣ x ) KL(q||p)=\sum_{k=1}^{K}{q(k|x)\log{q(k|x)}-q(k|x)\log{ p(k|x)}}K L ( q ∣∣ p )=k = 1∑Kq ( k ∣ x )ログ_q ( k ∣ x )−q ( k ∣ x )ログ_p ( k | x )
の前半はqq分布qqを考慮したqの定数qは固定ターゲット分布であり、KL 発散はクロス エントロピーとも呼ばれる後半にのみ関連します。
クロスエントロピー = − ∑ k = 1 K q ( k ∣ x ) log p ( k ∣ x ) CrossEntropy=-\sum_{k=1}^{K}q(k|x)\log{p( k|x)}クロスエントロピー_ _ _ _ _ _=−k = 1∑Kq ( k ∣ x )ログ_
2 つの分布p ( k | x )が近いほど、クロス エントロピーは小さくなり、逆にクロス エントロピーは大きくなります。
特に、バイナリ分類タスクの場合、バイナリ クロス エントロピー BCE (Binary Cross Entropy) があります。
BCE = − ( y log y ^ + ( 1 − y ) log ( 1 − y ^ ) ) BCE=-(y\ log{\hat{y}}+(1-y)\log{(1-\hat{y})})紀元前=− ( yログ_y^+( 1−y )ログ_( 1−y^) )
これは実際にはK = 2 K=2K=2特別な状況。
勾配
ロジスティック回帰の勾配表現は線形回帰と同じで、どちらも
θ j = θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) xj ( i ) \ theta_{j }=\theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^ {(i )})x_{j}^{(i)}}私j=私j−あるメートル1i = 1∑メートル( h ( x(私) ;私)−y( i ) )xj(私)
ロジスティック回帰では、h ( x ; θ ) = σ ( θ x ⊤ ) h(\boldsymbol{x};\boldsymbol{\theta})=\sigma{(\boldsymbol{\theta x^{\top }) であることに注意してください。 })}h ( x ;私)=σ ( θ x⊤ )の場合、線形回帰ではシグモイド演算は行われません。
具体的な導出は次のとおりです。
J ( θ ) = − [ y log p + ( 1 − y ) log ( 1 − p ) ] J(\boldsymbol{\theta})=-\left[ y\log{ p}+(1-y)\log{(1-p)}\right]J ( θ )=−[ yログ_p+( 1−y )ログ_( 1−p ) ]
インデックス、p = σ ( θ x ) p=\sigma(\ball シンボル{\theta x})p=σ ( θx )。線性法
による: ∂ J ∂ θ j = ∂ J ∂ p ∂ p ∂ ( θ x ) ∂ ( θ x ) ∂ θ j \frac{\partial{J}}{\partial{\theta_{ j}}}=\frac{\partial{J}}{\partial{p}}\frac{\partial{p}}{\partial{(\boldsymbol{\theta x})}}\frac{\partial {(\boldsymbol{\theta x})}}{\partial{\theta_{j}}}
∂θ _j∂ J=∂p _∂ J∂ ( θx )∂p _∂θ _j∂ ( θx )
で:
- ∂ J ∂ p = − yp + 1 − y 1 − p \frac{\partial{J}}{\partial{p}}=-\frac{y}{p}+\frac{1-y}{1 -p}∂p _∂ J=−pはい+1 − p1 − y
- ∂ p ∂ ( θ x ) = σ ( θ x ) ( 1 − σ ( θ x ) ) \frac{\partial{p}}{\partial{(\boldsymbol{\theta x})}}=\sigma( \boldsymbol{\theta x})(1-\sigma{(\boldsymbol{\theta x})})∂ ( θx )∂p _=σ ( θx ) ( 1−σ ( θx ) )
- ∂ ( θ x ) ∂ θ j = xj \frac{\partial{(\boldsymbol{\theta x})}}{\partial{\theta_{j}}}=x_{j}∂θ _j∂ ( θx )=バツj
1 つの方程式について、
J ( θ ) = [ − yp + 1 − y 1 − p ] σ ( θ x ) ( 1 − σ ( θ x ) ) xj = [ − y σ ( θ x ) + − y 1 − σ ( θ x ) ] σ ( θ x ) ( 1 − σ ( θ x ) ) xj = [ − y ( 1 − σ ( θ x ) ) + ( 1 − y ) σ ( θ x ) xj = ( σ ( θ x ) − y ) xj \begin{aligned} J(\ball シンボル{\theta})&=\left[-\frac{y}{p}+\frac{1-y}{1 -p}\ right]\sigma(\ballsymbol{\theta x})(1-\sigma{(\ballsymbol{\theta x})})x_{j}\\&=\left[-\frac{y }{\sigma (\ボール記号{\シータ x})}+\frac{1-y}{1-\sigma(\ボール記号{\シータ x})}\right]\sigma(\ボール記号{\シータ x} ) (1-\sigma{(\ボール シンボル{\theta x})})x_{j}\\ &=\left[-y(1-\sigma(\ボール シンボル{\theta x}))+(1 - y)\sigma(\ballsymbol{\theta x})\right]x_{j}\\ &=(\sigma(\ballsymbol{\theta x})-y)x_{j}\end{aligned}J ( θ )=[ −pはい+1−p1−はい]σ ( θx ) ( 1−σ ( θx ) ) xj=[ −σ ( θx )はい+1−σ ( θx )1−はい]σ ( θx ) ( 1−σ ( θx ) ) xj=[ − y ( 1−σ ( θx ))+( 1−y ) σ ( θx ) ]バツj=( σ ( θx )−y ) xj
過学習と過小学習
機械学習の分野では、過学習は常に重要な問題です。過学習とは、学習されたモデルに小さな偏差と過度の分散がある状況を指します。
たとえば、大規模な分類データ セットがあり、このデータ セットのラベルは特定の分布に準拠しており、モデルの目標はサンプルからこの分布へのマッピングを学習することです。このデータ セットをランダムに 10 個のサブセットに分割し、対応する 10 個のモデルをそれぞれトレーニングするとします。これら 10 個のモデルは独自のデータ セットで適切に分類できるはずであり、すべてのデータが1 つのデータセット。これは、モデルのバイアスと分散が比較的小さいことを意味します。
データセットの 1 つに含まれる「犬」サンプルがすべて白い犬であると仮定して、状況を考えてみましょう。このモデルでは、白い動物はすべて犬であると考えられます。これは「White Dog」データセットでは適切に分類できますが、他のモデルと比較すると、このモデルの「差」が大きすぎるように見えます。これは、偏差が小さい場合には分散が大きくなることを意味します。過学習とも呼ばれます。
逆に、偏差が大きく分散が小さい場合、つまりモデル間の差が非常に小さいが正確に分類できない場合、この状況はアンダーフィッティングと呼ばれます。
アンダーフィッティングの場合は、データを強化するか、反復回数を大幅に増やすことで解決できます。過学習については、正則化と呼ばれる手法を導入します。
正則化
最も一般的に使用される正則化方法は、パラメータが過学習の方向に発展するのを制御するために、損失関数の後にパラメータ ペナルティ項を追加することです。一般的な表現形式は次のとおりです。
正規化された損失 = L oss + λ ( θ ) 正規化された\ 損失 = 損失 + \lambda(\theta)定期的な損失_ _ _ _ _ _ _ =損失_+λ ( θ )このコードでは、 L 2 L^{2}
を実装します。L正化
損失関数は次
のようになります。 J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) log ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) ) log ( 1 − h θ ( x ( i ) ) ) ] + λ 2 m ∑ j = 1 n θ j 2 J\left( \theta \right)=\frac{1}{m}\sum\limits_ {i=1}^{m}{[-{
{y}^{(i)}}\log \left( { {
h}_{\theta }}\left( {
{x}^{(i) }} \right) \right)-\left( 1-{ {
y}^{(i)}} \right)\log \left( 1-{ {
h}_{\theta }}\left( {
{ x}^{(i)}} \right) \right)]}+\frac{\lambda }{2m}\sum\limits_{j=1}^{n}{\theta _{j}^{2 }}J(私)=メートル1i = 1∑メートル[ − y(私)ログ_( h私(バツ(私)))−( 1−y(私))ログ_( 1−h私(バツ(私)))]+2m_ _私j = 1∑ん私j2
勾配を見つけて、正規化された勾配を取得します。
g ( θ ) = 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) xj ( i ) + λ m θ jg(\theta )=\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i)})x_ {j}^ {(i)}}+\frac{\lambda }{m}\theta _{j}g ( i )=メートル1i = 1∑メートル( h ( x(私) ;私)−y( i ) )xj(私)+メートル私私j
無限小方程式の場合、次の式が得られます。
θ j = θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) xj ( i ) − λ m ∑ j = 1 n θ j = ( 1 − λ m ) θ j − α 1 m ∑ i = 1 m ( h ( x ( i ) ; θ ) − y ( i ) ) xj ( i ) \theta_{j }=\ theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)};\theta)-y^{(i )}) x_{j}^{(i)}}-\frac{\lambda}{m}\sum\limits_{j=1}^{n}{\theta_{j}}=\left(1- \frac {\lambda}{m}\right)\theta_{j}-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h(x^{(i)} ;\ シータ)-y^{(i)})x_{j}^{(i)}}私j=私j−あるメートル1i = 1∑メートル( h ( x(私) ;私)−y( i ) )xj(私)−メートル私j = 1∑ん私j=( 1−メートル私)私j−あるメートル1i = 1∑メートル( h ( x(私) ;私)−y( i ) )xj(私)
正則化によって実際にパラメータがある程度減少することがわかります。縮小の程度はλ / m \lambda / mに関係します。λ / mに関連します。
この図はL 2 L^{2}L2正則化パラメータの影響。破線は正規化項の損失等高線を表し、実線は非正規化損失関数の損失等高線を表します。どちらもw ~ \tilde{w}にありますw〜バランスを実現します。w 1 w_{1}でw1方向、パラメータが変化しても損失関数はあまり変化しませんが、w 2 w_{2}の場合w2この変化はより劇的であるように思われます。つまり、w 2 w_{2}w2w 1 w_{1} と比較w1損失関数値を大幅に削減できます。
L 2 L^{2}L2正則化により、損失関数の値を大幅に減少させる方向のパラメータがより適切に保存されますが、勾配に大きな影響を与えないため、損失関数の方向が大きく変化するのには役立ちません。
3. Python コードの実装
データの正規化と正則化も実装するロジスティック回帰クラスのコードを次に示します。
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def bce_loss(pred, target):
"""
计算误差
:param pred: 预测
:param target: ground truth
:return: 损失序列
"""
return -np.mean(target * np.log(pred) + (1-target) * np.log(1-pred))
class LogisticRegression:
"""
Logistic回归类
"""
def __init__(self, x, y, val_x, val_y, epoch=100, lr=0.1, normalize=True, regularize=None, scale=0, show=True):
"""
初始化
:param x: 样本, (sample_number, dimension)
:param y: 标签, (sample_numer, 1)
:param epoch: 训练迭代次数
:param lr: 学习率
"""
self.theta = None
self.loss = []
self.val_loss = []
self.n = x.shape[0]
self.d = x.shape[1]
self.epoch = epoch
self.lr = lr
t = np.ones(shape=(self.n, 1))
self.normalize = normalize
if self.normalize:
self.x_std = x.std(axis=0)
self.x_mean = x.mean(axis=0)
self.y_mean = y.mean(axis=0)
self.y_std = y.std(axis=0)
x = (x - self.x_mean) / self.x_std
self.y = y
self.x = np.concatenate((t, x), axis=1)
# self.val_x = (val_x - val_x.mean(axis=0)) / val_x.std(axis=0)
self.val_x = val_x
self.val_y = val_y
self.regularize = regularize
self.scale = scale
self.show = show
def init_theta(self):
"""
初始化参数
:return: theta (1, d+1)
"""
self.theta = np.zeros(shape=(1, self.d + 1))
def gradient_decent(self, pred):
"""
实现梯度下降求解
"""
# error (n,1)
error = pred - self.y
# term (d+1, 1)
term = np.matmul(self.x.T, error)
# term (1,d+1)
term = term.T
if self.regularize == "L2":
re = self.scale / self.n * self.theta[0, 1:]
re = np.expand_dims(np.array(re), axis=0)
re = np.concatenate((np.array([[0]]), re), axis=1)
# re [0,...] (1,d+1)
self.theta = self.theta - self.lr * (term / self.n + re)
# update parameters
else:
self.theta = self.theta - self.lr * (term / self.n)
def validation(self, x, y):
if self.normalize:
x = (x - x.mean(axis=0)) / x.std(axis=0)
outputs = self.get_prob(x)
curr_loss = bce_loss(outputs, y)
if self.regularize == "L2":
curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
self.val_loss.append(curr_loss)
predicted = np.expand_dims(np.where(outputs[:, 0] > 0.5, 1, 0), axis=1)
count = np.sum(predicted == y)
if self.show:
print("Accuracy on Val set: {:.2f}%\tLoss on Val set: {:.4f}".format(count / y.shape[0] * 100, curr_loss))
def test(self, x, y):
outputs = self.get_prob(x)
predicted = np.expand_dims(np.where(outputs[:, 0] > 0.5, 1, 0), axis=1)
count = np.sum(predicted == y)
# print("Accuracy on Test set: {:.2f}%".format(count / y.shape[0] * 100))
# curr_loss = bce_loss(outputs, y)
# if self.regularize == "L2":
# curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
return count / y.shape[0] # , curr_loss
def train(self):
"""
训练Logistic回归
:return: 参数矩阵theta (1,d+1); 损失序列 loss
"""
self.init_theta()
for i in range(self.epoch):
# pred (1,n); theta (1,d+1); self.x.T (d+1, n)
z = np.matmul(self.theta, self.x.T).T
# pred (n,1)
pred = sigmoid(z)
curr_loss = bce_loss(pred, self.y)
if self.regularize == "L2":
curr_loss += self.scale / self.n * np.sum(self.theta[0, 1:] ** 2)
self.loss.append(curr_loss)
self.gradient_decent(pred)
if self.show:
print("Epoch: {}/{}, Train Loss: {:.4f}".format(i + 1, self.epoch, curr_loss))
self.validation(self.val_x, self.val_y)
if self.normalize:
y_mean = np.mean(z, axis=0)
self.theta[0, 1:] = self.theta[0, 1:] / self.x_std.T
self.theta[0, 0] = y_mean - np.dot(self.theta[0, 1:], self.x_mean.T)
return self.theta, self.loss, self.val_loss
def get_prob(self, x):
"""
回归预测
:param x: 输入样本 (n,d)
:return: 预测结果 (n,1)
"""
t = np.ones(shape=(x.shape[0], 1))
x = np.concatenate((t, x), axis=1)
pred = sigmoid(np.matmul(self.theta, x.T))
return pred.T
def get_inner_product(self, x):
t = np.ones(shape=(x.shape[0], 1))
x = np.concatenate((t, x), axis=1)
return np.matmul(self.theta, x.T)
def predict(self, x):
prob = self.get_prob(x)
return np.expand_dims(np.where(prob[:, 0] > 0.5, 1, 0), axis=1)
4. 単次元および多次元のロジスティック分類
1次元のデータ分類
データセットの視覚化は
、トレーニング セットと検証セットを分割します。
トレーニング セットの視覚化:
検証セットの視覚化:
分類のためのアルゴリズムを呼び出します。
from LogisticRegression import LogisticRegression
epochs = 5000
alpha = 0.01
logistic_reg = LogisticRegression(x=train_x,y=train_y_ex,val_x=val_x,val_y=val_y_ex,epoch=epochs,lr=alpha)
theta,train_loss,val_loss = logistic_reg.train()
分類パフォーマンス
テストセットの精度: 80.00%
私の F1 スコア: 0.8571
sklearnライブラリ関数の検証
Sklearn 精度: 80.00%
Sklearn F1 スコア: 0.8571
意思決定の境界線を視覚化する
トレーニング プロセスを視覚化すると、
明らかな過学習があることがわかりますが、学習率と反復回数を調整することで抑制できます。もちろん、正則化も実行できます。
多次元データの分類
データ セットは、
トレーニング セットと検証セットに視覚的に分割されます
。トレーニング セット:
検証セット:
データ拡張を実行します (データ次元を拡張します)
{1}、x_{2}、x_{1}^{2}、x_{1}x_{2}、x_{2}^{2}、x_{1}^{ 3}、x_{1}^ {2}x_{2}、\cdots]バツ=[バツ1、バツ2、バツ12、バツ1バツ2、バツ22、バツ13、バツ12バツ2、⋯]
これを6乗展開すると
def feature_mapping(x, degree):
feature = np.zeros([x.shape[0],1])
for i in range(0, 1 + degree):
for j in range(0, 1 + degree - i):
if i==0 and j==0: continue
feature=np.concatenate((feature, np.expand_dims(np.multiply(np.power(x[:, 0], i) , np.power(x[:, 1], j)), axis=1)),axis=1)
return feature[:,1:]
train_x_map = feature_mapping(train_x,degree=6)
val_x_map = feature_mapping(val_x,degree=6)
正則化パラメータは 2 です
テストセットの精度: 66.67%
私の F1 スコア: 0.5556
Sklearn の精度: 70.83%
Sklearn の Val Loss: 0.3076
Sklearn F1 スコア: 0.6667
決定境界の視覚化の正則化パラメーター
は 0 です。決定境界の視覚化から、決定境界が過度に「変形」しているように見えることがわかります
。これは、過剰適合の顕著な兆候です。