Python: деректен өз есебіңізге дейін 46-сабақ (барлығы 56)
Сыныптау және қате матрицасы
Python курсының қырық бесінші сабағы. Модель «иә» не «жоқ» деп жауап береді: келесі жылы инфляция он пайыздан жоғары бола ма. Дәлдігі 0.75, ал әрқашан «жоқ» дейтін модельдікі 0.675 — әрі қате матрицасы сонда жиырма алты жоғары жылдың жиырмасы өткізіп жіберілгенін көрсетеді.
Не үшін керек
Осы уақытқа дейін модель санмен жауап беретін. Енді ол «иә» не «жоқ» дейді — әрі бұл басқа тектес қате: «жеті тармаққа жаңылды» емес, «басқаны айтты».
Мұндағы қате дәл екі түрлі әрі олардың бағасы әртүрлі. Жалған «иә» — бекер көтерілген дабыл. Өткізіп алу — керек кезде көтерілмегені. Дәлдік сияқты бір сан оларды араластырады, әрі бүкіл сабақ соларды қалай ажырату және араларынан қалай таңдау керегі туралы.
Бірден тұтас
klassifikaciya.py файлы. Дерек нағыз: 2000 жылдан бергі он көршінің жылдық инфляциясы, Дүниежүзілік банк. Әр жылға қойылатын сұрақ: келесі жылы инфляция он пайыз немесе одан жоғары бола ма.
"""45-сабақ: сыныптау және қате матрицасы.
Қатарлар нағыз: он көршінің жылдық инфляциясы, Дүниежүзілік банктің
FP.CPI.TOTL.ZG көрсеткіші. Сұрақ — иә не жоқ: келесі жылы инфляция он пайыз
немесе одан жоғары бола ма.
"""
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix
# Ел: қатар қай жылдан басталады және мөлшерлемелердің өзі, пайызбен.
INFLYACIYA = {
"Әзірбайжан": (2000, [1.81, 1.55, 2.77, 2.23, 6.71, 9.68, 8.33, 16.7, 20.85, 1.46,
5.73, 7.86, 1.07, 2.42, 1.37, 4.03, 12.44, 12.94, 2.27, 2.61,
2.76, 6.65, 13.85, 8.79, 2.21]),
"Армения": (2000, [-0.79, 3.15, 1.06, 4.72, 6.96, 0.64, 2.89, 4.41, 8.95, 3.41,
8.18, 7.65, 2.56, 5.79, 2.98, 3.73, -1.4, 0.97, 2.52, 1.44,
1.21, 7.18, 8.64, 1.98, 0.27]),
"Беларусь": (2000, [168.62, 61.13, 42.54, 28.4, 18.11, 10.34, 7, 8.43, 14.84, 12.95,
7.74, 53.23, 59.22, 18.31, 18.12, 13.53, 11.84, 6.03, 4.87, 5.6,
5.55, 9.46, 15.21, 5, 5.79]),
"Грузия": (2000, [4.06, 4.65, 5.59, 0.84, 5.66, 8.25, 9.16, 9.24, 10, 1.73,
7.11, 8.54, -0.94, -0.51, 3.07, 4, 2.13, 6.04, 2.62, 4.85,
5.2, 9.57, 11.9, 2.49, 1.11]),
"Қазақстан": (2000, [13.18, 8.35, 5.84, 6.44, 6.88, 7.58, 8.72, 10.85, 17.14, 7.32,
7.4, 8.45, 5.2, 5.94, 6.85, 6.68, 14.36, 7.44, 6.16, 5.33,
6.72, 8.04, 15.03, 14.53, 8.69]),
"Қырғызстан": (2000, [18.7, 6.92, 2.13, 2.97, 4.11, 4.34, 5.55, 10.23, 24.52, 6.84,
7.97, 16.64, 2.77, 6.61, 7.53, 6.5, 0.39, 3.18, 1.54, 1.13,
6.33, 11.91, 13.92, 10.75, 5]),
"Молдова": (2000, [31.3, 9.76, 5.3, 11.75, 12.52, 11.96, 12.78, 12.37, 12.78, -0.06,
7.48, 7.69, 4.55, 4.6, 5.09, 9.68, 6.36, 6.57, 3.05, 4.84,
3.77, 5.11, 28.74, 13.42, 4.68]),
"Ресей": (2000, [20.8, 21.48, 15.79, 13.66, 10.89, 12.69, 9.67, 9.01, 14.11, 11.65,
6.85, 8.44, 5.07, 6.75, 7.82, 15.53, 7.04, 3.68, 2.88, 4.47,
3.38, 6.69, 13.74, 5.87, 8.43]),
"Түркия": (2000, [54.92, 54.4, 44.96, 21.6, 8.6, 8.18, 9.6, 8.76, 10.44, 6.25,
8.57, 6.47, 8.89, 7.49, 8.85, 7.67, 7.78, 11.14, 16.33, 15.18,
12.28, 19.6, 72.31, 53.86, 58.51]),
"Өзбекстан": (2011, [13.78, 13.21, 11.84, 9.28, 8.75, 8.13, 13.88, 17.52, 14.53,
12.87, 10.85, 11.45, 9.96, 9.63]),
}
HIGH = 10.0 # «жоғары инфляция» дегеніміз қанша
CUT = 2015 # үйретудің соңғы жылы
def pairs(data):
"""«Осы жыл → келесі жыл» жұптары. Жауап екеуі де бар жерде ғана белгілі."""
rows = []
for country, (first, values) in data.items():
for i in range(len(values) - 1):
rows.append({"ел": country, "жыл": first + i,
"инфляция": values[i], "келесі": values[i + 1]})
table = pd.DataFrame(rows)
table["жоғары"] = (table["келесі"] >= HIGH).astype(int)
return table
table = pairs(INFLYACIYA)
train = table[table["жыл"] <= CUT]
test = table[table["жыл"] > CUT]
print("== Нені болжаймыз")
print(" «жыл → келесі жыл» жұбы:", len(table))
print(" олардың ішінде жоғары инфляциясы:", int(table["жоғары"].sum()),
f"({table['жоғары'].mean():.0%})")
print(" үйрету:", len(train), "жұп,", CUT, "жылды қоса алғанда")
print(" тексеру:", len(test), "жұп, одан кейін")
print()
print("== Әрқашан «жоқ» дейтін модель")
always_no = np.zeros(len(test), dtype=int)
print(" дәлдігі:", round(accuracy_score(test["жоғары"], always_no), 3))
print(" сонымен бірге ол бірде-бір жылды тапқан жоқ, барлығы",
int(test["жоғары"].sum()))
print()
print("== Логистикалық регрессия")
model = LogisticRegression().fit(train[["инфляция"]], train["жоғары"])
guess = model.predict(test[["инфляция"]])
print(" дәлдігі:", round(accuracy_score(test["жоғары"], guess), 3))
print(" «әрқашан жоқтан» ұтысы:",
round(accuracy_score(test["жоғары"], guess) - accuracy_score(test["жоғары"], always_no), 3))
print()
print("== Қате матрицасы")
tn, fp, fn, tp = confusion_matrix(test["жоғары"], guess).ravel()
print(pd.DataFrame(
[[tn, fp], [fn, tp]],
index=["шын мәнінде тыныш", "шын мәнінде жоғары"],
columns=["«жоқ» дедік", "«иә» дедік"],
).to_string())
print(" дұрыс «иә»:", tp, "—", tp + fn, "ішінен")
print(" жалған «иә»:", fp)
print(" өткізіп алғаны:", fn)
print()
print("== Жалған «иәнің» бағасы")
probability = model.predict_proba(test[["инфляция"]])[:, 1]
rows = []
for threshold in (0.2, 0.3, 0.5, 0.7):
said_yes = (probability >= threshold).astype(int)
tn, fp, fn, tp = confusion_matrix(test["жоғары"], said_yes).ravel()
rows.append({"табалдырық": threshold, "жалған «иә»": fp, "өткізіп алғаны": fn,
"дәлдігі": round(accuracy_score(test["жоғары"], said_yes), 3)})
print(pd.DataFrame(rows).set_index("табалдырық").to_string())
print(" табалдырық — статистика емес, қатенің бағасы туралы шешім")
Шығысы:
== Нені болжаймыз
«жыл → келесі жыл» жұбы: 229
олардың ішінде жоғары инфляциясы: 69 (30%)
үйрету: 149 жұп, 2015 жылды қоса алғанда
тексеру: 80 жұп, одан кейін
== Әрқашан «жоқ» дейтін модель
дәлдігі: 0.675
сонымен бірге ол бірде-бір жылды тапқан жоқ, барлығы 26
== Логистикалық регрессия
дәлдігі: 0.75
«әрқашан жоқтан» ұтысы: 0.075
== Қате матрицасы
«жоқ» дедік «иә» дедік
шын мәнінде тыныш 54 0
шын мәнінде жоғары 20 6
дұрыс «иә»: 6 — 26 ішінен
жалған «иә»: 0
өткізіп алғаны: 20
== Жалған «иәнің» бағасы
жалған «иә» өткізіп алғаны дәлдігі
табалдырық
0.2 14 4 0.775
0.3 10 10 0.750
0.5 0 20 0.750
0.7 0 23 0.713
табалдырық — статистика емес, қатенің бағасы туралы шешім
Талдау
«Иә не жоқ» есебі «иәнің» анықтамасынан басталады
Жоғары инфляция дегеніміз қанша? Сабақта он пайыз, әрі бұл дерек емес, шешім: бес болса, «иә» көпшілікке айналар еді, он бес болса — сиреп кетер еді. Мақсаттың анықтамасы — модельдің бөлігі, әрі оны есте емес, қасына жазады.
Уақыт бойынша кесу — өткен сабақтан: 2015 жылды қоса үйренеміз, одан кейінгісінде тексереміз. Мұнда араластыруға дәл сол себеппен болмайды.
«Иә» сирек болғанда дәлдік өтірік айтады
әрқашан «жоқ»: дәлдігі 0.675
логистикалық: дәлдігі 0.75
Ештеңе санамай, бәріне «жоқ» деп жауап беретін модель үш жағдайдың екеуінде дұрыс болып шығады — себебі жоғары инфляция жылдардың үштен бірінде кездеседі. 0.675-тен төмен кез келген дәлдік модельсіз қалғаннан нашар; 0.75 лайықты естіледі әрі жеті жүздік қосымша болып шығады.
Ереже: «иә не жоқ» есебінде дәлдікті «иәнің» үлесімен қатар ғана оқиды. Өздігінен ол сан ештеңе білдірмейді.
Қате матрицасы
«жоқ» дедік «иә» дедік
шын мәнінде тыныш 54 0
шын мәнінде жоғары 20 6
Бір санның орнына төрт ұяшық, әрі бүкіл сурет солардың ішінде. Сол жақ жоғарыда — дұрыс «жоқ», оң жақ төменде — дұрыс «иә». Қалған екі ұяшық — қатенің екі түрі: жалған «иә» (оң жақ жоғарыда) және өткізіп алу (сол жақ төменде).
Мұнда модельде жалған дабыл жоқ — әрі жиырма алтының жиырмасы өткізіп жіберілген. Ол дерлік әрқашан «жоқ» дейді, ал «иә» дегенде бірде-бір рет қателеспейді. Мұндай модельді сақ деп атау оңай; шын мәнінде ол дәл қолданбақ болған жерінде пайдасыз.
Табалдырықты тест жиынында емес, валидацияда таңдайды
жалған «иә» өткізіп алғаны дәлдігі
0.2 14 4 0.775
0.3 10 10 0.750
0.5 0 20 0.750
Осы шағын оқу мысалында уақыт бойынша бөлінген кейінгі бөлік табалдырықты таңдау үшін қолданылады, сондықтан ол тәуелсіз тест емес, валидация жиыны. Соңғы сапаны модель мен табалдырықты таңдауға қатыспаған кейінгі кезеңде бір рет өлшеу керек.
predict — бұл predict_proba және 0.5-пен салыстыру. Бұл жарты ештеңеден шықпайды: оны сіз үшін таңдаған, әрі оны жылжытуға болады.
Табалдырықты 0.2-ге жылжытыңыз — сонда модель жиырма алты жоғары жылдың жиырма екісін табады, бағасы он төрт жалған дабыл. 0.7-ге жылжытыңыз — дабыл мүлде жоқ, бірақ пайда да нөл. Дәлдік бұл кезде дерлік өзгермейді: 0.775, 0.750, 0.713 — ол мұндағы болып жатқанды көрмейді.
Қатенің бағасын сырттан қояды
Қай табалдырық дұрыс? Арзанырағы — ал бұл деректе жоқ сұрақ.
Өткізіп жіберілген инфляция жылы бес жалған дабылға тұрса, ең жақсы табалдырық 0.2. Керісінше, жалған дабыл өткізіп алудан бес есе қымбат болса, ең жақсысы — 0.5. Модель сол бір модель, дерек сол, ал жауап басқа. Бұл тапсырмада саналады, әрі мұндағы басты сабақ осы: машина қатені санайды, ал оның бағасын адам қояды.
Бұл есеп нені істей алмайды
Белгі біреу — ағымдағы жылдың инфляциясы. Мұндай белгімен модель дағдарысқа кіріп бара жатқан елді одан шығып келе жатқан елден тіпті ажырата алмайды: сандары бірдей, ал әрі қарайғысы әртүрлі.
Әрі тексеру жұбы сексен. Сексен бақылаудағы төрт ұяшық — шеттері кең баға: бір-екі бақылау ары-бері жылжыса, дәлдік те, табылған жоғары жылдардың саны да байқарлық өзгереді. Мұндай ұяшықтарды үшінші таңбаға дейін санаудың мәні жоқ.
Сабақ картасы
Өз сөзіңізбен айтыңыз
Қарамай, дауыстап немесе қағазға жауап беріңіз. Жауаптар — сабақтың соңында.
- Әрқашан «жоқ» дейтін модельдің дәлдігі неге 0.675?
- Жалған «иә» өткізіп алудан немен ерекшеленеді әрі оларды неге қосуға болмайды?
- 0.5 табалдырығы қайдан шығады әрі оны жылжыту нені білдіреді?
Жаттығу
Тапсырмаға дейінгі үш қысқа қадам: болжау, толықтыру, түзету. Жауаптар — сабақтың соңында, бірақ алдымен өзіңіз жауап беріңіз.
1. Болжаңыз. Он жылдың біреуі ғана жоғары болса, бағдарлама не басып шығарады?
from sklearn.metrics import accuracy_score
truth = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
always_no = [0] * 10
print("дәлдігі:", accuracy_score(truth, always_no))
print("табылған жоғары жыл:", sum(1 for t, g in zip(truth, always_no) if t == g == 1))
2. Бос орынды толтырыңыз. ... орнына матрицадан төрт санды алыңыз.
# матрицаның төрт саны: дұрыс «жоқ», жалған «иә», өткізіп алғаны, дұрыс «иә»
from sklearn.metrics import confusion_matrix
truth = [0, 0, 1, 1, 0, 1]
said = [0, 1, 1, 0, 0, 1]
tn, fp, fn, tp = ...
print("жалған «иә»:", fp, "— өткізіп алғаны:", fn)
3. Түзетіңіз. Бағдарлама 0.8 дәлдікті басып шығарады да, сонымен тоқтайды.
# бір дәлдік аз: ол қандай қате болғанын айтпайды
from sklearn.metrics import accuracy_score
truth = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
said = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
print("дәлдігі:", accuracy_score(truth, said))
Тапсырма
Міндетті. «Жыл → келесі жыл» жұптарын жинап, уақыт бойынша кесіңіз әрі бірде-бір жылдың екі бөлікке де түспегенін тексеріңіз. Логистикалық регрессияны үйретіп, 0.5 табалдырығындағы қате матрицасын басып шығарыңыз — массив емес, сөзбен жазылған төрт жолмен. Сосын 0.1-ден 0.7-ге дейінгі табалдырықтарды өтіп, кесте басыңыз: жалған «иә», өткізіп алғаны және дәлдігі. Соңында қатенің екі түрлі бағасы үшін ең жақсы табалдырықты санаңыз: өткізіп алу дабылдан бес есе қымбат болғанда және керісінше.
Күтілетін шығыс:
== Уақыт бойынша кесу
үйрету: 149 жұп, олардың жоғарысы 43
тексеру: 80 жұп, олардың жоғарысы 26
екі бөлікке де түскен жылдар: жоқ
== 0.5 табалдырығындағы матрица
дұрыс «жоқ»: 54
жалған «иә»: 0
өткізіп алғаны: 20
дұрыс «иә»: 6
== Барлық табалдырық
жалған «иә» өткізіп алғаны дәлдігі
табалдырық
0.1 38 0 0.525
0.2 14 4 0.775
0.3 10 10 0.750
0.4 5 15 0.750
0.5 0 20 0.750
0.6 0 22 0.725
0.7 0 23 0.713
== Бір сұраққа екі түрлі жауап
өткізіп алу дабылдан 5 есе қымбат: ең жақсы табалдырық 0.2 — жалған «иә» 14, өткізіп алғаны 4
дабыл өткізіп алудан 5 есе қымбат: ең жақсы табалдырық 0.5 — жалған «иә» 0, өткізіп алғаны 20
модель біреу, жауап әртүрлі: табалдырық дәлдік бойынша таңдалмайды
Дайын болғаны: шығыс жол-жолымен сәйкес келеді; матрица ұяшықтары сөзбен аталады; қатенің бағасы кодта санмен беріледі, көзбен таңдалмайды; ең жақсы табалдырық дәлдік бойынша емес, баға бойынша таңдалады.
Өз деректеріңізде. Өзіңіздің «иә не жоқ» сұрағыңызды ойлап табыңыз — сынақтан өтемін бе, сәлемдеме апта ішінде келе ме, жалақыға дейін ақша жете ме — әрі екі баған жазыңыз: не күткеніңіз және не болғаны. Жиырма жолда да матрица қай жаққа жиірек қателесетініңізді көрсетеді, ал бұл бір дәлдікпен білуге болмайтын нәрсе.
Қалауыңыз бойынша.
- Жоғары инфляцияның анықтамасын 10 %-дан 5 %-ға ауыстырып, «иәнің» үлесі мен төрт ұяшықтың қалай өзгеретінін қараңыз.
- Екінші белгі — инфляцияның жылдық өзгерісін — қосып, өткізіп алулармен не болатынын қараңыз.
precision_recall_curveтұрғызып, қолмен санаған табалдырықтарыңызды сол қисықтан табыңыз.
Жобада бұл қайда тұрады
Қадам жоқ. Жиынтық сандармен жауап береді, ал оны үш елде «жоғары инфляция бола ма» деп болжайтын нәрсеге айналдыру — курс қырық екінші сабақтан бері одан бас тартуға шақырып келе жатқан нәрсенің дәл өзі.
Бірақ осы сабақтың бір ережесі жиынтықта қазірдің өзінде жұмыс істейді, әрі оны дауыстап атаған жөн: беттегі әр цифрдың қасында қатесінің бағасы көрініп тұруға тиіс. Сондықтан тренд ең үлкен қателікпен, байланыс ел санымен, ал санаудан бас тарту немен жетпегенімен бірге басылады. Қате матрицасы — «иә» мен «жоқ» жауаптарына арналған сол ой.
Жауаптар
Жауаптарды көрсету
Сұрақтарға
- Өйткені жоғары инфляция жұптардың үштен бірінде кездеседі: әрқашан «жоқ» деп жауап берген модель қалған жағдайлардың бәрінде дұрыс болып шығады. Бұл модельдің сапасы емес, деректегі сирек жауаптың үлесі.
- Жалған «иә» — бекер көтерілген дабыл; өткізіп алу — керек кезде көтерілмегені. Оларды қосуға болмайды, себебі бағасы әртүрлі: бір жерде жалған дабыл — жұмсалған бір сағат, ал өткізіп алу — жоғалған ақша, басқа жерде керісінше.
- 0.5 табалдырығы —
predictдегеннің әдепкісі, есептің қасиеті емес. Оны жылжыту модельдің қандай сенімділігінен бастап жылды жоғары деп атауға келісетінімізді өзгерту дегені: табалдырық төмен болса — дабыл көп, өткізіп алу аз, жоғары болса — керісінше.
Жаттығуға
- Он жылдың тоғызы тыныш, сондықтан «әрқашан жоқ» тоғыз жағдайда дұрыс. Сонымен бірге жалғыз жоғары жылды ол таппады — жаттығудың бүкіл мәні осында.
дәлдігі: 0.9
табылған жоғары жыл: 0
confusion_matrix(truth, said, labels=[0, 1]).ravel().labelsаргументі формалдылық емес: онсыз бірде-бір «иә» жоқ деректе матрица 1 × 1 болып шығады да, төрт санға тарату бұзылады.
# матрицаның төрт саны: дұрыс «жоқ», жалған «иә», өткізіп алғаны, дұрыс «иә»
from sklearn.metrics import confusion_matrix
truth = [0, 0, 1, 1, 0, 1]
said = [0, 1, 1, 0, 0, 1]
tn, fp, fn, tp = confusion_matrix(truth, said, labels=[0, 1]).ravel()
print("жалған «иә»:", fp, "— өткізіп алғаны:", fn)
жалған «иә»: 1 — өткізіп алғаны: 1
- 0.8 дәлдікті бірде-бір рет «иә» демеген модель алды. Оның неше «иә» тапқанын да басу керек.
# бір дәлдік аз: ол қандай қате болғанын айтпайды
from sklearn.metrics import accuracy_score, confusion_matrix
truth = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
said = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
tn, fp, fn, tp = confusion_matrix(truth, said, labels=[0, 1]).ravel()
print("дәлдігі:", accuracy_score(truth, said))
print("дұрыс «иә»:", tp, "—", tp + fn, "ішінен")
дәлдігі: 0.8
дұрыс «иә»: 0 — 2 ішінен
Тапсырмаға
Соңғы екі жол — бәрі сол үшін саналды. Қатенің бір бағасында ең жақсы табалдырық 0.2, екіншісінде — 0.5, әрі бұл модель туралы дау емес: осы екі жолдың арасында модель мүлде өзгерген жоқ. Өзгергені — ненің қымбат екені, ал бұл білім деректен шықпайды.
0.1 табалдырығына назар аударыңыз: өткізіп алу нөл, бірақ елу төрт тыныш жылда отыз сегіз жалған дабыл. Дерлік әр жылға «жоғары инфляция» деп айқайлайтын модель формалды түрде ештеңе өткізбейді — әрі дәл сол себепті оған екінші рет ешкім сенбейді.
Дереккөздер
- confusion_matrix, scikit-learn — ұяшықтардың реті және
labelsне үшін керек. - LogisticRegression, scikit-learn — модель және оның
predict_proba. - Тұтыну бағасының инфляциясы, Дүниежүзілік банк — сабақ тұрғызылған қатарлар.
Пікірлер (0)
Пікір қалдыру үшін кіріңіз →
Әзірге пікір жоқ. Бірінші болыңыз.