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/vi/1-Introduction/04-stats-and-probability/notebook.ipynb

581 lines
21 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Giới thiệu về Xác suất và Thống kê\n",
"Trong sổ tay này, chúng ta sẽ thử chơi với một số khái niệm đã được thảo luận trước đây. Nhiều khái niệm từ xác suất và thống kê được thể hiện rất tốt trong các thư viện chính dùng để xử lý dữ liệu trong Python, chẳng hạn như `numpy` và `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": [
"## Biến ngẫu nhiên và Phân phối\n",
"Hãy bắt đầu bằng cách lấy một mẫu gồm 30 giá trị từ phân phối đều từ 0 đến 9. Chúng ta cũng sẽ tính toán trung bình và phương sai.\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": [
"Để ước tính bằng mắt có bao nhiêu giá trị khác nhau trong mẫu, chúng ta có thể vẽ **biểu đồ tần số**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.hist(sample)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Phân tích Dữ liệu Thực tế\n",
"\n",
"Giá trị trung bình và phương sai rất quan trọng khi phân tích dữ liệu thực tế. Hãy tải dữ liệu về các cầu thủ bóng chày từ [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": [
"> Chúng ta đang sử dụng một gói có tên là [**Pandas**](https://pandas.pydata.org/) ở đây để phân tích dữ liệu. Chúng ta sẽ nói thêm về Pandas và làm việc với dữ liệu trong Python ở phần sau của khóa học này.\n",
"\n",
"Hãy cùng tính giá trị trung bình cho tuổi, chiều cao và cân nặng:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[['Age','Height','Weight']].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Bây giờ hãy tập trung vào chiều cao và tính toán độ lệch chuẩn và phương sai:\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": [
"Ngoài giá trị trung bình, cũng nên xem xét giá trị trung vị và các phân vị. Chúng có thể được trực quan hóa bằng **biểu đồ hộp**:\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": [
"Chúng ta cũng có thể tạo biểu đồ hộp của các tập con trong bộ dữ liệu của mình, ví dụ, nhóm theo vai trò của người chơi.\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": [
"> **Lưu ý**: Sơ đồ này cho thấy, trung bình, chiều cao của những người chơi ở vị trí chạy cơ sở đầu tiên cao hơn chiều cao của những người chơi ở vị trí chạy cơ sở thứ hai. Sau này chúng ta sẽ học cách kiểm tra giả thuyết này một cách chính thức hơn, và cách chứng minh rằng dữ liệu của chúng ta có ý nghĩa thống kê để xác nhận điều đó. \n",
"\n",
"Tuổi, chiều cao và cân nặng đều là các biến ngẫu nhiên liên tục. Bạn nghĩ phân phối của chúng là gì? Một cách tốt để tìm hiểu là vẽ biểu đồ tần suất các giá trị: \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": [
"## Phân phối Chuẩn\n",
"\n",
"Hãy tạo một mẫu trọng lượng nhân tạo tuân theo phân phối chuẩn với trung bình và phương sai giống như dữ liệu thực của chúng ta:\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": [
"Vì hầu hết các giá trị trong cuộc sống thực đều phân phối chuẩn, chúng ta không nên sử dụng bộ phát số ngẫu nhiên đều để tạo dữ liệu mẫu. Dưới đây là điều xảy ra nếu chúng ta cố gắng tạo trọng lượng với phân phối đều (được tạo bởi `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": [
"## Khoảng tin cậy\n",
"\n",
"Bây giờ chúng ta hãy tính khoảng tin cậy cho cân nặng và chiều cao của các cầu thủ bóng chày. Chúng ta sẽ sử dụng mã [từ cuộc thảo luận stackoverflow này](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": [
"## Kiểm định Giả thuyết\n",
"\n",
"Hãy cùng khám phá các vai trò khác nhau trong bộ dữ liệu cầu thủ bóng chày của chúng ta:\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": [
"Hãy kiểm tra giả thuyết rằng các cầu thủ chơi ở vị trí Chạy đế một cao hơn các cầu thủ chơi ở vị trí Chạy đế hai. Cách đơn giản nhất để làm điều này là kiểm tra các khoảng tin cậy:\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": [
"Chúng ta có thể thấy rằng các khoảng không chồng lấp nhau.\n",
"\n",
"Một cách thống kê chính xác hơn để kiểm tra giả thuyết là sử dụng **kiểm định t của Student**:\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": [
"Hai giá trị trả về bởi hàm `ttest_ind` là:\n",
"* p-value có thể được xem là xác suất hai phân phối có cùng trung bình. Trong trường hợp của chúng ta, giá trị này rất thấp, nghĩa là có bằng chứng mạnh mẽ ủng hộ việc các cầu thủ gắn bó vị trí baseman đầu tiên cao hơn.\n",
"* t-value là giá trị trung gian của sự khác biệt trung bình đã chuẩn hóa được sử dụng trong kiểm định t, và nó được so sánh với giá trị ngưỡng cho một mức độ tin cậy nhất định.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mô phỏng phân phối chuẩn với Định lý Giới hạn Trung tâm\n",
"\n",
"Bộ tạo số giả ngẫu nhiên trong Python được thiết kế để cho chúng ta một phân phối đều. Nếu chúng ta muốn tạo một bộ tạo cho phân phối chuẩn, chúng ta có thể sử dụng định lý giới hạn trung tâm. Để có được một giá trị phân phối chuẩn, chúng ta chỉ cần tính trung bình của một mẫu được tạo ra từ phân phối đều.\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": [
"## Tương quan và Evil Baseball Corp\n",
"\n",
"Tương quan cho phép chúng ta tìm mối quan hệ giữa các chuỗi dữ liệu. Trong ví dụ minh họa của chúng ta, hãy giả sử có một tập đoàn bóng chày ác độc trả lương cho các cầu thủ theo chiều cao - người chơi càng cao thì tiền lương nhận được càng nhiều. Giả sử có lương cơ bản là 1000 đô la, và thêm tiền thưởng từ 0 đến 100 đô la, tùy thuộc vào chiều cao. Chúng ta sẽ lấy các cầu thủ thật từ MLB và tính toán mức lương tưởng tượng của họ:\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": [
"Bây giờ chúng ta sẽ tính hiệp phương sai và tương quan của các dãy số đó. `np.cov` sẽ cho chúng ta cái gọi là **ma trận hiệp phương sai**, là sự mở rộng của hiệp phương sai cho nhiều biến. Phần tử $M_{ij}$ của ma trận hiệp phương sai $M$ là tương quan giữa các biến đầu vào $X_i$ và $X_j$, và các giá trị trên đường chéo $M_{ii}$ là phương sai của $X_{i}$. Tương tự, `np.corrcoef` sẽ cho chúng ta **ma trận tương quan**.\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": [
"Một hệ số tương quan bằng 1 có nghĩa là có một **mối quan hệ tuyến tính** mạnh mẽ giữa hai biến. Chúng ta có thể nhìn thấy mối quan hệ tuyến tính này bằng cách vẽ một giá trị lên trục so với giá trị kia:\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": [
"Hãy xem điều gì xảy ra nếu mối quan hệ không phải là tuyến tính. Giả sử công ty của chúng ta quyết định ẩn đi sự phụ thuộc tuyến tính rõ ràng giữa chiều cao và mức lương, và đưa vào một số tính phi tuyến trong công thức, chẳng hạn như `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": [
"Trong trường hợp này, hệ số tương quan hơi nhỏ hơn một chút, nhưng vẫn khá cao. Bây giờ, để làm cho mối quan hệ trở nên kém rõ ràng hơn, chúng ta có thể muốn thêm một số sự ngẫu nhiên bằng cách thêm một biến ngẫu nhiên vào lương. Hãy xem điều gì sẽ xảy ra:\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": [
"> Bạn có đoán được tại sao các dấu chấm lại xếp thành các đường thẳng đứng như thế này không?\n",
"\n",
"Chúng ta đã quan sát được mối tương quan giữa một khái niệm được thiết kế nhân tạo như lương và biến quan sát được *chiều cao*. Hãy cùng xem liệu hai biến quan sát được, chẳng hạn như chiều cao và cân nặng, cũng có tương quan không:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thật không may, chúng ta không thu được kết quả nào - chỉ có một số giá trị `nan` kỳ lạ. Điều này là do một số giá trị trong chuỗi của chúng ta không xác định, được biểu diễn dưới dạng `nan`, điều này khiến kết quả của phép toán cũng trở nên không xác định. Bằng cách xem ma trận, chúng ta có thể thấy rằng `Weight` là cột gây vấn đề, vì tự tương quan giữa các giá trị `Height` đã được tính toán.\n",
"\n",
"> Ví dụ này cho thấy tầm quan trọng của việc **chuẩn bị dữ liệu** và **làm sạch dữ liệu**. Nếu không có dữ liệu thích hợp, chúng ta không thể tính toán được gì.\n",
"\n",
"Hãy sử dụng phương pháp `fillna` để điền các giá trị thiếu, và tính toán tương quan:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thực sự có sự tương quan, nhưng không mạnh như trong ví dụ nhân tạo của chúng ta. Thật vậy, nếu chúng ta nhìn vào biểu đồ phân tán của một giá trị so với giá trị kia, mối quan hệ sẽ ít rõ ràng hơn nhiều:\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": [
"## Kết luận\n",
"\n",
"Trong sổ tay này, chúng ta đã học cách thực hiện các phép toán cơ bản trên dữ liệu để tính các hàm thống kê. Giờ đây, chúng ta biết cách sử dụng một bộ công cụ toán học và thống kê vững chắc nhằm chứng minh một số giả thuyết, cũng như cách tính khoảng tin cậy cho các biến tùy ý dựa trên một mẫu dữ liệu.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Tuyên bố miễn trừ trách nhiệm**: \nTài liệu này đã được dịch bằng dịch vụ dịch thuật AI [Co-op Translator](https://github.com/Azure/co-op-translator). Mặc dù chúng tôi nỗ lực đảm bảo độ chính xác, xin lưu ý rằng bản dịch tự động có thể chứa lỗi hoặc không chính xác. Tài liệu gốc bằng ngôn ngữ gốc nên được xem là nguồn thông tin chính xác và đáng tin cậy. Đối với các thông tin quan trọng, khuyến khích sử dụng dịch vụ dịch thuật chuyên nghiệp của con người. Chúng tôi không chịu trách nhiệm đối với bất kỳ sự hiểu lầm hoặc diễn giải sai nào phát sinh từ việc sử dụng bản dịch này.\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-16T16:45:18+00:00",
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
"language_code": "vi"
}
},
"nbformat": 4,
"nbformat_minor": 4
}