You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Data-Science-For-Beginners/translations/sr/1-Introduction/04-stats-and-probability/notebook.ipynb

581 lines
23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Увод у вероватноћу и статистику\n",
"У овом нотебуку ћемо се играти са неким од концепата које смо раније дискутовали. Многи концепти из вероватноће и статистике су добро представљени у главним библиотекама за обраду података у Python-у, као што су `numpy` и `pandas`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import random\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Случајне променљиве и расподеле\n",
"Хајде да почнемо са цртањем узорка од 30 вредности из једнолике расподеле од 0 до 9. Такође ћемо израчунати средњу вредност и варијансу.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sample = [ random.randint(0,10) for _ in range(30) ]\n",
"print(f\"Sample: {sample}\")\n",
"print(f\"Mean = {np.mean(sample)}\")\n",
"print(f\"Variance = {np.var(sample)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Да бисмо визуелно проценили колико различитих вредности има у узорку, можемо нацртати **хистограм**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.hist(sample)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Анализа стварних података\n",
"\n",
"Средња вредност и дисперзија су веома важни приликом анализе стварних светских података. Хајде да учитамо податке о бејзбол играчима са [SOCR MLB Height/Weight Data](http://wiki.stat.ucla.edu/socr/index.php/SOCR_Data_MLB_HeightsWeights)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(\"../../data/SOCR_MLB.tsv\",sep='\\t', header=None, names=['Name','Team','Role','Weight','Height','Age'])\n",
"df\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Ми користимо пакет зван [**Pandas**](https://pandas.pydata.org/) за анализу података. Више ћемо говорити о Pandas-у и раду са подацима у Питону касније у овом курсу.\n",
"\n",
"Израчунaјмо просечне вредности за старост, висину и тежину:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[['Age','Height','Weight']].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сада хајде да се фокусирамо на висину и израчунамо стандардну девијацију и варијансу:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(list(df['Height'])[:20])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mean = df['Height'].mean()\n",
"var = df['Height'].var()\n",
"std = df['Height'].std()\n",
"print(f\"Mean = {mean}\\nVariance = {var}\\nStandard Deviation = {std}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поред средње вредности, има смисла погледати и медијану и квартиле. Они се могу визуализовати помоћу **бокс плота**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,2))\n",
"plt.boxplot(df['Height'].ffill(), vert=False, showmeans=True)\n",
"plt.grid(color='gray', linestyle='dotted')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Такође можемо направити кутијасте дијаграме за подскупове нашег скупа података, на пример, груписане по улози играча.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.boxplot(column='Height', by='Role', figsize=(10,8))\n",
"plt.xticks(rotation='vertical')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Напомена**: Овај дијаграм сугерише да су просечне висине првих базмена веће од висина других базмена. Касније ћемо научити како можемо формалније тестирати ову хипотезу и како показати да су наши подаци статистички значајни за то.\n",
"\n",
"Године, висина и тежина су све континуиране случајне променљиве. Шта мислите какав им је распоред? Добар начин да то сазнате је да исцртате хистограм вредности:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df['Weight'].hist(bins=15, figsize=(10,6))\n",
"plt.suptitle('Weight distribution of MLB Players')\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Count')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Нормална расподела\n",
"\n",
"Хајде да креирамо вештачки узорак тежина који следи нормалну расподелу са истим средњом вредношћу и варијансом као и наши стварни подаци:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generated = np.random.normal(mean, std, 1000)\n",
"generated[:20]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(generated, bins=15)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(np.random.normal(0,1,50000), bins=300)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Пошто су већина вредности у стварном животу нормално распоређене, не бисмо требали користити униформни генератор случајних бројева за генерисање узорка података. Ево шта се дешава ако покушамо да генеришемо тежине са униформном дистрибуцијом (генерисано помоћу `np.random.rand`):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"wrong_sample = np.random.rand(1000)*2*std+mean-std\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(wrong_sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Интервали поуздања\n",
"\n",
"Хајде сада да израчунамо интервале поуздања за тежине и висине бејзбол играча. Користићемо код [са ове stackoverflow расправе](https://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import scipy.stats\n",
"\n",
"def mean_confidence_interval(data, confidence=0.95):\n",
" a = 1.0 * np.array(data)\n",
" n = len(a)\n",
" m, se = np.mean(a), scipy.stats.sem(a)\n",
" h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)\n",
" return m, h\n",
"\n",
"for p in [0.85, 0.9, 0.95]:\n",
" m, h = mean_confidence_interval(df['Weight'].fillna(method='pad'),p)\n",
" print(f\"p={p:.2f}, mean = {m:.2f} ± {h:.2f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Тестирање хипотеза\n",
"\n",
"Хајде да истражимо различите улоге у нашем скупу података о бејзбол играчима:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.groupby('Role').agg({ 'Weight' : 'mean', 'Height' : 'mean', 'Age' : 'count'}).rename(columns={ 'Age' : 'Count'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Хајде да тестирамо хипотезу да су играчи прве базе виши од играча друге базе. Најједноставнији начин да то урадимо је да тестирамо интервале поузданости:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for p in [0.85,0.9,0.95]:\n",
" m1, h1 = mean_confidence_interval(df.loc[df['Role']=='First_Baseman',['Height']],p)\n",
" m2, h2 = mean_confidence_interval(df.loc[df['Role']=='Second_Baseman',['Height']],p)\n",
" print(f'Conf={p:.2f}, 1st basemen height: {m1-h1[0]:.2f}..{m1+h1[0]:.2f}, 2nd basemen height: {m2-h2[0]:.2f}..{m2+h2[0]:.2f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можемо видети да се интервали не преклапају.\n",
"\n",
"Статистички исправнији начин да се докаже хипотеза је коришћењем **Student t-теста**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from scipy.stats import ttest_ind\n",
"\n",
"tval, pval = ttest_ind(df.loc[df['Role']=='First_Baseman',['Height']], df.loc[df['Role']=='Second_Baseman',['Height']],equal_var=False)\n",
"print(f\"T-value = {tval[0]:.2f}\\nP-value: {pval[0]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Две вредности које враћа функција `ttest_ind` су:\n",
"* p-вредност се може сматрати вероватноћом да две дистрибуције имају исти просек. У нашем случају, она је врло ниска, што значи да постоје чврсти докази који подржавају да су први базични играчи виши.\n",
"* t-вредност је посредна вредност нормализоване разлике просека која се користи у t-тесту, и упоређује се са праговном вредношћу за дати ниво поверења.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Симулација нормалне расподеле помоћу централне граничне теореме\n",
"\n",
"Псеудо-рандом генератор у Пајтону је дизајниран да нам да једноличну расподелу. Ако желимо да креирамо генератор за нормалну расподелу, можемо користити централну граничну теорему. Да бисмо добили нормално распоређену вредност, једноставно ћемо израчунати средњу вредност узорка добијеног једноличним генератором.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def normal_random(sample_size=100):\n",
" sample = [random.uniform(0,1) for _ in range(sample_size) ]\n",
" return sum(sample)/sample_size\n",
"\n",
"sample = [normal_random() for _ in range(100)]\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Корелација и Зла бејзбол корпорација\n",
"\n",
"Корелација нам омогућава да пронађемо везе између секвенци података. У нашем примеру за игру, претпоставимо да постоји зла бејзбол корпорација која плаћа своје играче у зависности од њихове висине - што је играч виши, то више новца добија. Претпоставимо да постоји базична плата од 1000 долара и додатни бонус од 0 до 100 долара, у зависности од висине. Узећемо праве играче из МЛБ-а и израчунати њихове замишљене плате:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"heights = df['Height'].fillna(method='pad')\n",
"salaries = 1000+(heights-heights.min())/(heights.max()-heights.mean())*100\n",
"print(list(zip(heights, salaries))[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Хајде сада да израчунамо коваринацију и корелацију тих секвенци. `np.cov` ће нам дати такозвану **матрицу коваринације**, која представља проширење коваринације на више променљивих. Елемент $M_{ij}$ матрице коваринације $M$ је корелација између улазних променљивих $X_i$ и $X_j$, а дијагоналне вредности $M_{ii}$ представљају дисперзију $X_i$. Слично томе, `np.corrcoef` ће нам дати **матрицу корелације**.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f\"Covariance matrix:\\n{np.cov(heights, salaries)}\")\n",
"print(f\"Covariance = {np.cov(heights, salaries)[0,1]}\")\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Корелација једнака 1 значи да постоји јака **линеарна веза** између две променљиве. Можемо визуелно видети линеарну везу тако што ћемо нацртати једну вредност у односу на другу:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights,salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Хајде да видимо шта се дешава ако релација није линеарна. Претпоставимо да је наша корпорација одлучила да сакрије очигледну линеарну зависност између висина и плата, и увела неку нелинеарност у формулу, као што је `sin`:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"У овом случају, корелација је нешто мања, али је и даље прилично висока. Сада, да бисмо везу учинили још мање очигледном, можда ћемо хтети да додамо неку додатну случајност додавањем неке случајне променљиве на плату. Хајде да видимо шта се дешава:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100+np.random.random(size=len(heights))*20-10\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights, salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Можете ли да погодите зашто се тачке поређају у вертикалне линије овако?\n",
"\n",
"Посматрали смо корелацију између вештачки конструисаног концепта као што је зарада и посматране варијабле *висина*. Хајде да видимо да ли се две посматране варијабле, као што су висина и тежина, такође корелирају:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Нажалост, нисмо добили никакве резултате - само неке чудне `nan` вредности. То је због тога што су неке вредности у нашој серији неодређене, представљене као `nan`, што узрокује да и резултат операције буде неодређен. Гледајући матрицу можемо видети да је `Weight` проблематичан колона, зато што је израчуната аутокорелација између вредности `Height`.\n",
"\n",
"> Овај пример показује значај **припреме података** и **чишћења**. Без одговарајућих података не можемо ништа израчунати.\n",
"\n",
"Хајде да користимо методу `fillna` да попунимо недостајуће вредности и израчунамо корелацију: \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Постоји заиста корелација, али не толико јака као у нашем вештачком примеру. Заиста, ако погледамо дијаграм распршења једне вредности у односу на другу, веза би била знатно мање очигледна:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(df['Weight'],df['Height'])\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Height')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Закључак\n",
"\n",
"У овом бележнику смо научили како изводити основне операције на подацима ради израчунавања статистичких функција. Сада знамо како користити комплетан скуп математичких и статистичких алата да бисмо доказали неке хипотезе и како обрачунати интервале поузданости за произвољне променљиве узевши узорак података.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Одрицање од одговорности**:\nОвај документ је преведен коришћењем AI сервиса за превођење [Co-op Translator](https://github.com/Azure/co-op-translator). Док се трудимо да обезбедимо прецизност, молимо имајте у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати ауторитетним извором. За критичне информације препоручује се стручни људски превод. Нисмо одговорни за било каква неспоразумевања или погрешне тумачења настала употребом овог превода.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
},
"coopTranslator": {
"original_hash": "0f899e3c5019f948e7c787b22f3b2304",
"translation_date": "2026-01-16T20:26:10+00:00",
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
"language_code": "sr"
}
},
"nbformat": 4,
"nbformat_minor": 4
}