Mở đầu
Bài viết dưới sẽ đề cập đến w loại phân phối:
- Phân phối nhị thức
- Phân phối chuẩn (Gaussian)
Phân phối là gì
Một phân phối xác xuất là một hàm số cho biết xác xuất của các kết quả khác nhau trong mộ thí nghiệm.
Với tất cả phân phối có 3 khái niệm quan trọng:
- Trung bình
- Độ biến thiên
- Độ lệch chuẩn
Phân phối nhị thức
Chúng ta sẽ bắt đầu bằng phân phối nhị thức vì nó là phân phối dễ hiểu nhất.
Các điều kiện để phân phối là nhị thức (biến ngẫu nhiên là nhị thức):
- Số lần thí nghiệm là hằng số không thay đổi.
- Các thí nghiệm độc lập. Trong trường hợp lấy mẫu không hoàn lại thì việc lấy mẫu trong những thí nghiệm trước sẽ ảnh hưởng số mẫu lấy được trong thí nghiệm sau. Tuy nhiên có luật 10%: Khi thí nghiệm đòi hỏi lấy mẫũ không hoàn lại, nếu số mẫu nhỏ hơn 10% so với tổng hợp, ta có thể coi là thí nghiệm là độc lập. Luật 10% sẽ cho ta kết qủa tính xác xuất trong thì nghiệm không hoàn lại gần bằng thí nghiệm hoàn lại.
- Xác xuất thành công không thay đổi cho tất cả các thí nghiệm.
- Sau mỗi thí nghiệm ta biết kết qủa của thí nghiệm là thành công hay thất bại.
Bài toán: Nếu tung một con xúc xắc 5 lần. Tính xác xuất 1,2,3,4,5 lần tung xúc xắc có mặt ngửa là 6.
Đầu tiên, ta kiểm tra xem bài toán có thỏa mãn các điều kiện để sử dụng phân phối nhị phân ha khong
Hàm khối xác xuất:
Trong đó:
- p là xác xuất thành công
- n là số thí nghiệm
- k là số lần thí nghiệm có kết qủa là thành công
Công thức tính số lần lấy được tập hợp thí nghiệm thành công k từ tổng hợp tất cả các thí nghiệm. Dưới đây là công thức tính tổ hợp (chọn phần tử từ nhóm lớn mà không phân biệt thứ tự), có thể quen thuộc với nhiều bạn.
Gọi X là tổng số lần xúc xắc có mặt ngửa trong 5 lần tung. Thử áp dụng công thức tính xác xuất trong 5 lần tung có 3 lần là mặt ngửa là 6.
Đầu tiên, ta tính tổ hợp tung xúc xắc có 3 mặt ngửa là 6 trong 5 lần tung:
Ta tung xúc xắc 5 lần, đây là số lần thí nghiệm. Ta coi kết qủa thí nghiệm là thành công khi ta tung xúc xắc có mặt ngửa là 6. Xác xuất ta tung được xúc xắc có mặt ngửa là 6 là 1/6. Bây giờ ta áp dụng công thức tính xác xuất:
Bây giờ ta sẽ vẽ barchart cho phân phối nhị thức cho tất cả số lần tung có mặt ngửa khi này dựa vào công thức tính xác xuất nhị phân đề cập ở trên. Viết code sẽ nhanh hơn.
from scipy.stats import binom
import matplotlib.pyplot as plt
k = [1, 2, 3, 4, 5]
n = 5
p = 1/6
binom_probs = binom.pmf(k, n, p, loc=0)
fig, ax = plt.subplots(1, 1, figsize=(20, 10))
ax.bar(k, binom_probs)
ax.set_xlabel("Số lần tung được mặt ngửa là 6")
ax.set_ylabel("Xác xuất")
Ta sẽ có được hình vẽ dưới đây:
Ta có thể thấy, là trong 5 lần tung xúc xắc, số lần ta tung mặt ngửa càng tăng, thì xác xuất ta có mặt ngửa là 6 sẽ giảm dần.
Trung bình
Công thức tính trung bình cho phân phối nhị thức là
Với bài toán trên, trung bình sẽ là
Code:
mean = binom.mean(n, p, loc=0)
mean
Độ biến thiên và độ lệch chuẩn
Công thức tính độ biến thiên:
Với bài toán trên, độ biến thiên sẽ là:
Code:
var = binom.var(n, p, loc=0)
var
Công thức tính độ lệch chuẩn chỉ đơn giản là căn bậc hai độ lệch chuẩn.
Với bài toán trên, độ lệch chuẩn sẽ là:
Code:
var = binom.var(n, p, loc=0)
var
Phân phối chuẩn
Khái niệm và tính chất
Dùng nhiều trong toán thống kê. Một trong những loại phân bố quan trọng nhất. Có nhiều loại dữ liệu theo phân phối chuẩn như chiều cao của người trong lớp học, điểm số của người trong lớp học, số giầy... Trong data science, bạn sẽ gặp các dữ liệu có phân phối chuẩn nhiều nhất.
Phân phối chuẩn có hình dạng như sau:
Phân phối chuẩn trông giống cái chuông. như dưới đây:
Ví dụ không phải phân phối chuẩn:
Phân phối chuẩn có một số các tính chất sau:
- Trung bình = Trung vị = yếu vị
- Trung bình sẽ ở chỏm của phân phối (chỗ cao nhất trong phân phối)
- Đối xứng ở giữa (trung bình). 50% dữ liệu nhỏ hay lớn hơn trung bình
Để biết dữ liệu có phải là phân phối chuẩn hay không, ta có thể vẽ histogram và kiểm tra hình vẽ có hình chuông hay không. Trong scipy có function để kiểm tra dữ liệu mẫu là phân phối chuẩn hay không, như code dưới đây (ví dụ lấy trực tiếp từ doc). Có một số loại test khác' . Nó cho ta biết là nhiều khả năng phân phối là phân phối chuẩn (không chính xác 100% nhưng đáng tin cậy).
scipy.stats.normaltest¶
>>> from scipy import stats
>>> pts = 1000
>>> np.random.seed(28041990)
>>> a = np.random.normal(0, 1, size=pts)
>>> b = np.random.normal(5, 1, size=pts)
>>> x = np.concatenate((a, b))
>>> k2, p = stats.normaltest(x)
>>> alpha = 1e-3
>>> print("p = {:g}".format(p))
p = 1.66728e-136 # Đây không phải là phân phối chuẩn.
# Nếu xác xuất có được dữ liệu ngẫu nhiên nhỏ hơn ý nghĩa thống kê alpha là 0.001, đây không phải là phân phối chuẩn
>>> if p < alpha:
... print("The null hypothesis can be rejected")
... else:
# Nhiều khả năng đây là phân phối chuẩn.
... print("The null hypothesis cannot be rejected")```
# Ngoài ra còn shapiro() anderson(), nên sử dụng hết để kiểm tra
Nếu vẽ hình ta sẽ thấy nó không phải là phân phối chuẩn vì ta kết hợp dữ liệu từ hai phân phối chuẩn thành một dữ liệu, trong đó hai phân phối chuẩn có trung bình lệch nhau.
Bài toán
Bài toán: Phân tích dữ liệu của về chiều cao của học sinh từ file dữ liệu sau đây bằng các tính chất trong phân phối chuẩn: https://www.kaggle.com/mustafaali96/weight-height/data#
Trước hết ta phải xem dữ liệu trông như thế nào:
df = pd.read_csv("./weight-height.csv")
df.head(5)
Height ở đây là chiều cao, ta thấy chiều cao 68.78 là hơi lạ, vì đây là dữ liệu lấy từ Mỹ, ta cần convert từ "inch" sang cm. Sau đó vẽ histogram:
df["Height_cm"] = df["Height"] * 2.54
df.hist(column="Height_cm", figsize=(14, 6), bins=40)
Quan sát ta có thể thấy, dữ liệu về chiều cao về học sinh này có phân phối chuẩn.
Trung bình
Tìm trung bình của dữ liệu có phân phối chuẩn rất đơn giản sử dụng code sau:
df["Height_cm"].mean() # Trung bình là: 168.57360177724595
# Vẽ đường trung bình màu đỏ trong phân phối chuẩn
axes = df.hist(column="Height_cm", figsize=(14, 6), bins=40)
axes[0][0].axvline(x=df["Height_cm"].mean(), color='r', linestyle='-')
Phương sai và Độ lệch chuẩn
Điều cần lưu ý là khi tính phương sai và độ lệch chuẩn, ta phải tính theo trường hợp dữ liệu của chúng ta là tổng hợp hay là dữ liệu mẫu. Dữ liệu chúng ta lấy là dữ liệu mẫu từ học sinh của một trường. Tuy nhiên, vì bài viết này đề cập đến vấn đề cơ bản trong phân phối chuẩn. Tạm thời ta coi đây là dữ liệu tất cả học sinh của một trường và ta muốn tình phương sai và độ lệch chuẩn của chiều cao tất cả học sinh của một trường. Công thức tính phương sai và độ lệch chuẩn và phương sai của dữ liệu mẫu sẽ được để cập trong các bài viết sau
# 10 quan sát đầu, trong dữ liệu chiều cao của học sinh:
>>> df["Height_cm"].head(10)
0 187.571423
1 174.706036
2 188.239668
3 182.196685
4 177.499761
5 170.822660
6 174.714106
7 173.605229
8 170.228132
9 161.179495
>>> height_series = df["Height_cm"]
# Implement công thức tính phương sai
>>> variance = ((height_series - height_series.mean())**2).sum()/height_series.size
>>> variance
95.49653347672371
# Tính phương sai sử dụng function trong dataframe. Kết quả tương tự như dùng công thức
>>> df["Height_cm"].var(ddof=0)
97.49653347672371
# Implement công thức tính độ lệch chuẩn
>>> std = np.sqrt(((height_series - height_series.mean())**2).sum()/height_series.size)
>>> std
9.772232778476152
# Tính độ lệch chuẩn sử dụng function trong dataframe. Kết quả tương tự như dùng công thức
>>> df["Height_cm"].std(ddof=0)
9.772232778476152
PDF (Probability Density Function)
PDF (probability density function) là hàm số cho biết xác xuất của một biến ngẫu nhiên rơi vào một khoảng gía trị. Thay bằng có một gía trị bất kỳ.
Khi tính xác xuất của một biến số liên tục, rất ít khi có bài toán nào đòi tính xác xuất họ sinh có chiều cao là 180 mà 179.5 đến 180.5 chẳng hạn. Vì số học sinh có chiều cao chính xác là 180.000000... (không sai 1 nanometer) sẽ gần như bằng 0, nên xác xuất cũng sẽ bằng 0. Sử dụng PDF, ta có thể vẽ được đường cong (màu đỏ) thể hiện phân bố chiều cao của học sinh như nhìn thấy ở dưới đây. Ví dụ với phân phối này, học sinh ở Mỹ có chiều cao từ 155 đến 180.
Code để vẽ hình trên:
# pdf
from scipy.stats import norm
x = df["Weight"].sort_values(ascending=True).copy()
fig, ax = plt.subplots(1, 1, figsize=(12,8))
df.hist(column="Weight", ax=ax, bins=20)
ax2 = ax.twinx()
ax2.plot(x, norm.pdf(x, x.mean(), x.std(ddof=0)), 'r-', lw=5, alpha=0.6, label='norm pdf')
plt.show()
CDF (Cumulative Distribution Function)
CDF (cumulative distribution function): Hàm số cho biết xác xuất một biến số ngẫu nhiên nhỏ hơn một gía trị. CDF sẽ có giá trị từ 0 đến 1.
Hình vẽ cho thấy PDF và CDF của chiều cao học sinh.
Code để vẽ hình trên:
# cdf
fig, ax = plt.subplots(2, 1, figsize=(14,12))
x = df["Height_cm"].sort_values(ascending=True).copy()
ax[0].plot(x, norm.pdf(x, x.mean(), x.std(ddof=0)), 'r-', lw=5, alpha=0.6, label='norm pdf')
ax[0].fill_between(x,y,0,where=(x>120) & (x<=180),color='y')
ax[0].set_xlabel("height cm")
ax[0].set_ylabel("PDF")
ax[0].set_title("PDF")
ax[1].plot(x, norm.cdf(x, x.mean(), x.std(ddof=0)), 'g-', lw=5, alpha=0.6, label='norm cdf')
ax[1].set_xlabel("height cm")
ax[1].set_ylabel("CDF")
ax[1].set_title("CDF")
ax[1].axvline(x=180, color='r', linestyle='-')
plt.show()
CDF cho ta biết diện tích dưới đường cong của PDF. Ví dụ ta muốn tìm diện tích dưới đường cong PDF nhỏ hơn 180 (diện tích màu vàng). Nói đơn giản hơn, ta muốn tìm xác xuất học sinh có chiều cao nhỏ hơn 180, ta tìm gía trị của hàm số CDF khi chiều cao học sinh bằng 180 (đường màu đỏ). CDF cho ta biết xác xuất chiều cao học sinh nhỏ hơn 180 sẽ gần bằng 0.9
Chính xác hơn, sử dụng code dưới đây, ta sẽ tính xác xuất học sinh có chiều cao nhỏ hơn 180 là 0.88
>>> norm.cdf(180, x.mean(), x.std(ddof=0))
0.8788529709136117
Phân phối chuẩn tắc
Phân phối chuẩn tắc (standard normal distribution) là phân phối chuẩn với giá trị trung bình (μ) bằng 0 và độ lệch chuẩn (σ) bằng 1.
Để biến phân phối chuẩn thành một phân phối chuẩn tắc ta sẽ biến đổi từng gía trị trong dữ liệu thành z-score:
Với bất kỳ dữ liệu nào, nếu phân phối chuẩn có trung bình hay độ lệch chuẩn khác nhau, khi biến thành phân phối chuẩn tắc sẽ đều có hình dạng (đường cong pdf) giống nhau, như sau:
Lý do vì phân phối chuẩn tắc sẽ có trung bình bằng 0 và độ lệch chuẩn là 1.
# Tính z-score bằng công thức
>>> x = df["Height_cm"].sort_values().copy()
>>> z_scores = (x - x.mean())/x.std(ddof=0)
>>> z_scores
# array([-3.14618407, -3.05424395, -2.98747835, ..., 3.16079789,
# 3.18501297, 3.2830986 ])
# Tính z-score bằng hàm số trong scipy
>>> from scipy.stats import zscore
>>> zscore(x)
array([-3.14618407, -3.05424395, -2.98747835, ..., 3.16079789,
3.18501297, 3.2830986 ])
# Trung bình của giá trị chuyển về z-score gần bằng 0
>>> z_scores.mean()
# 8.640199666842818e-16
# Độ lệch chuẩn của giá trị chuyển về z-score gần bằng 1
>>> z_scores.std()
# 1.0000500037503124
# Vẽ PDF
fig, ax = plt.subplots(1, 1, figsize=(10,6))
ax.plot(z_scores, norm.pdf(z_scores, z_scores.mean(), z_scores.std(ddof=0)), 'r-', lw=5, alpha=0.6, label='norm pdf')
Luật 68 - 95 - 99.7 (Emperical rule)
Luật 68 - 95 - 99.7 cho biết rằng, trong phân phối chuẩn tắc:
- Giá trị có z-score cách trung bình từ -1 đến 1 sẽ có xác xuất gần bằng: 68%
- Giá trị có z-score cách trung bình từ -2 đến 2 sẽ có xác xuất gần bằng: 95%
- Giá trị có z-score cách trung bình từ -2 đến 2 sẽ có xác xuất gần bằng: 97.7%
Ta có thể tính xác xuất này dựa vào phân phối chuẩn tắc từ chiều cao học sinh. Từ mục trước. Ví dụ a muốn tính diện tích (màu vàng) dưới đường cong PDF từ z-score là -1 đến 1, tính xác xuất học sinh z-score chiều cao từ -1 đến 1. Để làm vậy ta chỉ cần lấy CDF của z-score=1 (diện tích z-score <= 1) trừ đi CDF của z-score=-1 (diện tích của z-score <= -1)
Code dưới đây tính xác xuất của z-score từ -1 đến 1, -2 đến 2, -3 đến 3 :
>>> cdf_1 = norm.cdf(1, x.mean(), x.std(ddof=0))
>>> cdf_minus_1 = norm.cdf(-1, x.mean(), x.std(ddof=0))
>>> (cdf_1 - cdf_minus_1) * 100
68.26894921370861
>>> cdf_2 = norm.cdf(2, x.mean(), x.std(ddof=0))
>>> cdf_minus_2 = norm.cdf(-2, x.mean(), x.std(ddof=0))
>>> (cdf_2 - cdf_minus_2) * 100
95.44997361036417
>>> cdf_3 = norm.cdf(3, x.mean(), x.std(ddof=0))
>>> cdf_minus_3 = norm.cdf(-3, x.mean(), x.std(ddof=0))
>>> (cdf_3 - cdf_minus_3) * 100
99.73002039367398
Ta thấy sử dụng code trên, ta thấy phân phối chuẩn tắc có xác xuất như trong luật 68 - 95 - 99.7. Luật này rất bạn sẽ sử dụng nhiều trong toán thống kê.
Ví dụ bạn có thể ước chừng được là: xác xuất học có được học sinh từ 149.1 (z-score gần bằn -2) đến 188.1 (z-score gằng bằng 2) là khoảng 95%.
Trường hợp khác nếu có bài toán hỏi bạn, trong dữ liệu này, 68% phần lớn học sinh có chiều cao là bao nhiêu. Bạn có thể tính ngược lại từ công thức z-score:
>>> df["Height_cm"].mean() + (df["Height_cm"].std(ddof=0) * -1)
158.80136899876982
>>> df["Height_cm"].mean() + (df["Height_cm"].std(ddof=0) * 1)
178.3458345557221
Sử dụng code trên bạn có thể nói là 68% phẩn lớn học sinh có chiều cao từ 159 đến 178.
Kết luận
Bài viết này đề cập đến hai loại phân phối được sử dụng trong toán thống kê, hi vọng các bạn có học được thêm hoặc ôn lại một số các kiến thức liên quan đến phân phối để áp dụng vào việc phân tích dữ liệu. Bài viết sau sẽ đề cập đến các khái niệm khác trong phân phối: phân phối poisson, cộng trừ, nhân phân phối.