predict_proba()の各列は、学習済みモデルのclasses_と対応させて読みます。 2列目を見ただけで「陽性の確率」と決めないでください。目的のラベルを確認し、そのラベルがどの位置にあるかを調べてから列を取り出します。

対象は、scikit-learnで分類モデルを作り、予測確率を表やCSVへまとめたい学習者です。fitとpredict、NumPyの行列の基本が分かる人を想定しています。今回は架空の数値と色ラベルを使い、実在の人や申請の合否を判定しません。

公式資料の確認日は2026年11月2日です。以下はscikit-learn 1.9.1の単一出力分類を対象とする練習です。小さな架空データは列対応の説明用で、モデルの精度・将来の成果・業務利用への適性を示す評価ではありません。

predict_probaの配列を、classes_と対応させる

最初に、行・列・ラベルの三つを分ける

predict_proba()の結果を見るときは、一つの行がどの入力に対応し、一つの列がどのクラスに対応するかを分けて考えます。数値の配列だけを印刷すると、元のIDとクラス名が表示されないため、「この0.7は何の確率か」が曖昧になりやすくなります。

公式のclasses_の用語説明では、predict_probaの列とclasses_の対応が説明されています。ラベルが文字列なら、入力した順序や人が使いたい表示順と一致するとは限りません。配列の先頭から読み替える前に、学習済みモデルを確認します。

例えば、モデルのclasses_がblue, green, redなら、列0がblue、列1がgreen、列2がredです。説明用に確率が0.1, 0.2, 0.7だった場合、redに対応する値は0.7になります。この3値は関係を示す架空の配列で、後述の学習実行の出力値を引用したものではありません。

説明用の列対応。ラベルの値と、配列の位置を分ける
配列の列位置classes_のラベル説明用の値
0blue0.1
1green0.2
2red0.7

同じことは、ラベルが数値の場合にも当てはまります。ラベルの値が5だからといって、5列目へ入るわけではありません。クラスが5と10の2種類なら、出力の列数は2です。「ラベル5」と「列位置5」は別のものとして扱ってください。

架空の3色分類で、学習後のclasses_を表示する

まず、数値一つを使ってblue・green・redを分ける教材を作ります。学習用の行は、色順に並べず混ぜてあります。それでも、クラスの一覧を元の行順から推測せず、学習後のモデルから取得します。実際の特徴量の意味付けや分類性能の検証は、今回の範囲に含めません。

import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression

train = pd.DataFrame({"signal": [4, -2, 1, 3, -3, 0, 5, -1, 2]})
y = np.array(["red", "blue", "green", "red", "blue",
              "green", "red", "blue", "green"])
model = LogisticRegression(max_iter=1000).fit(train, y)

query = pd.DataFrame({"signal": [-2, 1, 4]},
                     index=["Q10", "Q30", "Q20"])
proba = model.predict_proba(query)
print(model.classes_)
print(proba.shape)
assert model.classes_.tolist() == ["blue", "green", "red"]
assert proba.shape == (3, 3)

ここで確かめるのは、入力3行に対して出力が3行あり、学習済みの3クラスに対応する3列があることです。3行3列の形が分かっただけでは、まだ各行と各列の意味は揃っていません。query.indexとmodel.classes_を付けて初めて、人が読みやすい表へ進めます。

max_iterはこの練習を実行するための設定です。この値を増やせば分類が良くなる、すべてのデータで収束する、といった意味にはしません。実データでは警告や学習の状況を確認し、別の問題として扱います。列対応の確認と、モデルを選ぶ作業を分けましょう。

また、別のモデルを読み込んだときや、学習データのクラスが変わったときは、以前のclasses_を使い回さないでください。今回の3色が別の色へ変わっても、列数だけは3のままかもしれません。形の一致は、ラベルの一致を保証しません。

確率配列へ、モデル自身のラベルを付ける

表へ変換するときの列名には、手書きのリストではなくmodel.classes_を使います。行には、確率を計算したqueryのIDを付けます。これで、「Q20のredの値」というように、二つの名前を使って場所を選べるようになります。

scores = pd.DataFrame(proba, columns=model.classes_, index=query.index)
print(scores.round(3))
red_score = scores["red"]
assert scores.index.tolist() == ["Q10", "Q30", "Q20"]
assert scores.columns.tolist() == ["blue", "green", "red"]
assert np.allclose(scores.sum(axis=1), 1)
assert np.allclose(red_score.to_numpy(), proba[:, 2])

この練習では、各行のクラス確率の合計が1になることも確認しています。ただし、列ラベルを誤って付けても合計は1のままです。「合計が合う」という数値の検算だけで、クラス名との対応まで正しいと判断しないようにします。

また、配列の行数とIDの数が同じであっても、IDの順番が違えば別の入力へ確率を付けることになります。IDを後から別ファイルから読み足すより、予測に使った表のインデックスをそのまま引き継ぐ方が、対応を追いやすくなります。

公式のLogisticRegressionのAPIには、確率出力とクラス順の説明があります。今回はこのモデルの単一出力で確認します。別のライブラリや複数出力の推定器へ、そのまま同じ配列構造を当てはめないでください。

2列目が陽性とは限らない例を、数値ラベルで確かめる

二値分類の教材では、ラベル0と1を使い、[:, 1]で1の確率を取る例をよく見ます。その記法だけを覚えて、どのラベルを学習したかを確認しないと、目的のクラスと反対側の確率を取り出す場合があります。ここではredを5、blueを10というラベルへ置き換えます。

keep = y != "green"
y_binary = np.where(y[keep] == "red", 5, 10)
binary = LogisticRegression(max_iter=1000).fit(train.loc[keep], y_binary)
binary_proba = binary.predict_proba(query)
print(binary.classes_)
assert binary.classes_.tolist() == [5, 10]

positive_label = 5
positions = np.flatnonzero(binary.classes_ == positive_label)
assert len(positions) == 1
positive_column = int(positions[0])
assert positive_column == 0
positive_scores = binary_proba[:, positive_column]

この教材で「注目するクラス」として5を選ぶと、対応するのは列0です。列1はラベル10のblueへ対応します。[:, 1]の1は配列の位置であり、モデルが「陽性」という意味を自動的に付けた印ではありません。

ラベルが0と1の場合でも、何を1と定義したかはデータ作成側の約束です。クラス名の仕様を確認せず、1を好ましい結果や高いリスクの意味へ読み替えないでください。どのクラスを取り出すか、ラベルの説明と一緒にコードへ残します。

「数値として大きいラベルほど陽性」という決まりもありません。5と10は識別のために付けた値です。ラベルの大小、クラスの頻度、モデルの確率、業務上の重要度は、それぞれ別の情報です。まずは列を選ぶ目的を、色の名前で説明できる状態にしましょう。

目的のラベルが存在しないときは、先に停止する

別のデータで学習し直すと、取り出したいクラスがモデルに存在しない場合があります。列がないことを見ずに位置を決めると、別のクラスを選んだり、想定していない配列アクセスになったりします。ラベル検索の結果が一つであることを確認してから使います。

def probability_for_label(fitted, inputs, label):
    classes = np.asarray(fitted.classes_)
    if classes.ndim != 1:
        raise ValueError("単一出力分類のラベル配列を確認してください")
    found = np.flatnonzero(classes == label)
    if len(found) != 1:
        raise ValueError(f"対象ラベルが一つに定まりません: {label!r}")
    values = np.asarray(fitted.predict_proba(inputs))
    if values.ndim != 2 or values.shape[1] != len(classes):
        raise ValueError("確率配列とクラス一覧の形を確認してください")
    return values[:, int(found[0])]

assert np.allclose(probability_for_label(binary, query, 5), positive_scores)
try:
    probability_for_label(binary, query, 99)
except ValueError:
    print("99は学習済みクラスにないため停止")
else:
    raise AssertionError("不在のラベルを見逃しています")

ここで99を0の確率として埋めていないのは、モデルがそのクラスを学習していないことと、確率0を出したことは違うからです。列がない理由を確認せずに補うと、後の比較表で「モデルが否定した結果」のように見える可能性があります。

この関数は練習用の単一出力分類に範囲を絞っています。すべての推定器で使える共通関数と考えず、実際のclasses_とpredict_probaの返り値をAPI資料で確認してください。複数の目的変数を扱うモデルでは、一覧や出力がリスト構造になる場合があります。

確認の際は、ラベルの型もメモします。数値の5を学習したモデルと、文字列の"5"を学習したモデルは、同じラベル仕様だと決めないでください。CSVやJSONへ結果を渡す途中で、列名やラベルが文字列として扱われる場面もあります。出力先の見出しが5と見えるだけで、元のラベルの型まで同じとは判断できません。

型を揃える必要があるときは、学習時と結果を利用する側の両方で、変換の約束を決めます。取り出しに失敗した直後に、ラベルを何となく文字列や数値へ変えて試すと、どの仕様で学習したかが見えなくなります。まず元のクラス一覧、表示した値の表現、データを読み込んだ時点の型を確認する方が、後日の再現につながります。

表示順・行ID・評価の意味を保って結果を渡す

表示順を変えるときは、列名ではなく列全体を移動する

色の見本帳ではred・green・blueの順に並べたいかもしれません。その場合も、最初にモデルの列順で表を作り、その後でラベル名を指定して並べ替えます。配列へいきなり希望の列名を付けると、数値とラベルの対応を入れ替えてしまいます。

display_order = ["red", "green", "blue"]
display_scores = scores.loc[:, display_order]
assert np.allclose(display_scores["red"], scores["red"])
assert np.allclose(display_scores["blue"], scores["blue"])
assert np.allclose(display_scores.sum(axis=1), scores.sum(axis=1))
print(display_scores.round(3))

この操作では、redという列に付いていた値がそのまま先頭へ移ります。見出しだけをredへ変更したわけではありません。表の順番を変えた後は、注目ラベルの列を元の表と比べると、対応を維持できているか確認できます。

列順を変えるときの判断
操作何が変わるか今回の扱い
classes_を列名へ使う配列に意味を付ける最初の表で行う
ラベル名で列を選び直す値と見出しを一緒に移す表示順の変更に使う
希望順の列名だけを付ける値の意味を読み違える可能性使わない
model.classes_を書き換えるモデルの内部対応へ影響しうる表示目的では行わない

列順が気に入らないからといって、学習済みモデルのclasses_を書き換えて解決しようとしないでください。表示を整える作業は、モデルから出た表の側で行います。モデルの情報と、資料の見せ方を分けておくと再現例を作りやすくなります。

希望の表示順に存在しないラベルがある場合も、先に確認します。誤った名前や過去のクラス名が混ざっていたら、表の加工へ進む前に止めます。知らない列を自動で追加するより、表示仕様とモデルのクラス一覧を突き合わせる方が原因を追いやすくなります。

predictのラベルと、argmaxの位置を取り違えない

argmaxが返すのは、最大値のある位置です。最大確率のラベル名そのものではありません。今回のLogisticRegressionの例では、最大の列位置をclasses_でラベルへ戻し、predictの結果と照合できます。位置の配列を予測ラベルとして保存しないでください。

positions = proba.argmax(axis=1)
labels_from_proba = model.classes_[positions]
predicted = model.predict(query)
print(positions)
print(labels_from_proba)
assert labels_from_proba.tolist() == ["blue", "green", "red"]
assert np.array_equal(labels_from_proba, predicted)

この例では位置が0・1・2、ラベルがblue・green・redです。位置とラベルがどちらも数値のモデルでは、間違いに気づきにくくなります。二値の5・10というラベルなら、位置0・1をそのまま保存していないかを意識して見てください。

一方、すべての分類器でpredictと確率の最大値の関係を同じように一般化しません。使う推定器や決定規則を確認する必要があります。今回の一致は、掲載したモデルと入力に対する検算です。任意のモデルで一致を保証するテストではありません。

表示用の表で先に列順を変えた場合は、argmaxの位置に対応する列名も変わります。元のmodel.classes_を、並べ替え後の位置へそのまま当てないようにします。ラベル付き表のidxmaxを使う方法もありますが、同値の扱いなど必要な仕様は別に確認しましょう。

行IDを残し、並べ替え後も同じ入力へ戻れるようにする

今回は入力IDをQ10・Q30・Q20の順にしています。見た目の昇順とは異なりますが、この順番のまま予測したので、結果にも同じIDを付けます。結果だけを数値順へ並べ替えた後に、元のIDの並びを付け直すと、別の行へ確率を割り当ててしまいます。

result = scores.copy()
result["predicted_label"] = predicted
sorted_result = result.sort_index()
assert sorted_result.index.tolist() == ["Q10", "Q20", "Q30"]
assert np.allclose(sorted_result.loc["Q20", model.classes_].to_numpy(dtype=float),
                   scores.loc["Q20"].to_numpy())
assert result.index.is_unique

表の並べ替えでは、値とIDを一緒に移動します。予測の前に欠損行を除いた場合や、途中で重複を整理した場合にも同じ確認が必要です。入力の行が減った理由を残し、予測対象外のIDを別に記録すると、結果がない行を確率0と誤解しにくくなります。

IDを列として持つ場合には、予測する特徴量へIDまで渡していないかも見ます。IDは対応を確認するために使い、今回の学習モデルの特徴量はsignalだけです。モデルが何を入力としたかと、結果を照合するキーを混同しないようにしてください。

結果をCSVへ出すときは、行IDをどの列へ保存したか、確率列の見出しがどのラベルか、予測ラベルが位置番号へ変わっていないかを確認します。本稿は保存処理を実行しませんが、読み戻した表でもこの三つを追える形式にすることが学習の目標です。

今回の入力IDと予測ラベル。行順を変えても対応は維持する
入力ID入力signalこの教材の予測ラベル
Q10-2blue
Q301green
Q204red

たとえば、IDを昇順に並べた表はQ10・Q20・Q30になります。予測ラベルもそのIDに合わせてblue・red・greenへ移るのが、この例での対応です。元のラベル配列blue・green・redを、並べ替え後の表へ位置だけで付けると、Q20とQ30の意味が入れ替わります。行数もラベル数も3のままなので、形だけの確認では見つけられません。

この確認に、確率が最大の行だけを使う必要はありません。先頭・途中・末尾のIDを一つずつ選び、そのIDの特徴量、元の確率行、並べ替え後の確率行を比較します。少ない教材では手で追い、実データではIDで結合する設計を検討する、という順に進めると、配列の位置に頼った受け渡しを減らせます。

0.8という値だけで「8割当たる」と判断しない

列対応を直しても、モデルの確率の質まで確認できたことにはなりません。正しいクラスの列を選べたかという問題と、出力された値をどの程度信頼できるかという問題は別です。今回の小さな教材から、実際の分類の正答率を報告しないでください。

公式の確率校正の説明では、予測確率と実際の頻度の関係を評価する考え方が説明されています。単に0.8という数値を見ただけで、その一件が8割の確率で正しいと確認できたわけではありません。別の評価用データで確かめる作業が必要です。

しきい値を使う場合も、まずどのラベルの列を使うかを固定します。その上で、しきい値によってどの入力を選ぶか、選ばなかった入力をどう扱うかを設計します。列を間違えたまましきい値を調整すると、見ているクラスそのものが反対になる場合があります。

学習用の資料には、モデル名、確認したライブラリ版、学習対象ラベル、取り出したラベル、しきい値の有無を書き残します。「確率が高い」という説明だけでなく、何に対する値かが分かるようにします。これは結果を派手に見せるためではなく、数値の意味を後から追うためです。

独学の確認課題と、質問先へ渡す再現メモを作る

この練習を終えたら、ラベルの文字を別の名前へ変え、classes_の並びがどうなるかを見ます。次に、数値ラベルの5と10のどちらを注目クラスにするか切り替えてください。列番号を手で変えるのではなく、選ぶラベルを変えるだけで取り出せるかを確認します。

続いて、表示順だけを変えた表と元の表で、同じラベルの確率が一致するかを比べます。最後に入力の行順を変え、ID付きの結果として追えるかを試します。クラスの列と入力の行は別の軸なので、一方が正しいだけでは十分ではありません。

質問するときは、学習後のclasses_、確率配列の形、取り出したいラベル、使った式、元の入力IDを示します。実際の顧客情報などを持ち込まず、今回のような小さい架空例へ置き換えてから相談すると、列対応の疑問へ焦点を絞れます。

講座を比較する場合は、分類のAPIを動かすだけなのか、ラベルの意味・データ分割・評価・結果の受け渡しまで扱うのかを確認します。Python基礎と機械学習の専門講座では前提が異なるため、今どこで止まっているかを説明してから範囲を相談してください。個別課題の添削や質問期間、総額は申込前に確認します。

復習用の確認表も作っておくと便利です。説明を読んだ直後は理解したつもりでも、別のラベルや行順では同じ操作を再現できないことがあります。以下の四つを、コードを丸写しせずに説明できるか確認します。答えを知らない入力を増やす前に、小さな期待値を自分で決めておくための課題です。

独学で確認する四つのケース
変更するもの保ちたい対応確認する場所
3色の表示順redの数値は同じラベルを指定した元表と表示表
注目ラベルを5から10へ選ぶ列は対応するクラスへ変わるbinary.classes_と抽出列
ラベル99を要求別クラスを代わりに選ばず停止対象ラベルの存在確認
入力IDの表示順Q20は同じ入力の結果を持つ並べ替え前後のID付き表

質問先へ相談するときも、四つすべてを一度に変えず、一つだけで起きる違いを示します。「モデルが逆に予測する」という表現だけでは、確率の列を読み違えたのか、表示順でラベルを付け替えたのか、入力IDをずらしたのかが分かりません。元の表・変えた操作・期待する対応の三つを揃えると、学習課題が具体的になります。

学習記録には、使ったモデルを作り直した日も残します。同じコードのファイル名でも、学習し直したモデルと、以前計算した確率表を混ぜている場合があります。列名を付けるときのモデルと、確率を計算したときのモデルが同じかも確認してください。クラスの数が変わらなくても、別の学習結果へ置き換わっている可能性があります。

PythonWinnerのAI・機械学習コースも、学習範囲を比較する際の候補です。分類モデルを動かす練習に加えて、クラス名と確率表を対応させる説明まで質問したい場合は、今回の小さな例を相談事項にできます。公式の講座案内を確認した上で、自分の前提知識に合うか、持ち込み課題への対応、受講総額、質問できる回数・期間を確認しましょう。この事例の個別添削が含まれるとは断定できません。確認日:2026年11月2日。

広告:【PythonWinner】

よくある質問

Q. predict_probaの2列目は、いつも陽性クラスですか?
A.

列は学習済みモデルのclasses_へ対応させて読みます。どのクラスを陽性と呼ぶかはデータ側の定義です。掲載した5と10の二値例で5を注目クラスにすると、対応するのは先頭列です。

Q. classes_と、ラベルを最初に入力した順番が違います。
A.

入力順から推測せず、学習後のclasses_を確認してください。掲載した3色の例ではblue・green・redの並びになります。表示の順序を変える場合は、結果の表で列全体を移動します。

Q. ラベル5の確率は5列目から取るのですか?
A.

ラベルの値と配列の列位置は別です。クラスが5と10の2種類なら、確率の列数は2です。classes_からラベル5の位置を調べて選びます。

Q. 欲しいラベルの列がないので、0で足してよいですか?
A.

今回の手順では停止して確認します。モデルがクラスを学習していないことと、そのクラスへ確率0を出したことは異なります。学習対象、ラベル変換、読み込んだモデルを調べてください。

Q. argmaxで返った0や1を予測ラベルとして使えますか?
A.

argmaxが返すのは最大値の位置です。今回の例では、その位置に対応するclasses_からラベルを取り出します。位置とラベルが偶然同じ数値の例だけで覚えないようにします。

Q. 複数の目的変数を同時に予測するモデルにも使えますか?
A.

本稿は単一出力分類に範囲を絞っています。複数出力ではクラス一覧や確率がリストなどの構造になる場合があります。対象推定器の公式APIと実際の返り値を確認して設計し直してください。