Chuyển đến nội dung chính

Tìm hiểu độ lệch và độ nhọn (skewness, kurtosis) và cách trực quan hóa chúng

Hướng dẫn trực quan toàn diện về độ lệch/độ nhọn và cách chúng ảnh hưởng đến phân phối dữ liệu và cuối cùng là tới dự án khoa học dữ liệu của bạn.
Đã cập nhật 5 thg 6, 2026  · 10 phút đọc

Sau khi thu thập dữ liệu và dành hàng giờ để làm sạch, cuối cùng bạn có thể bắt đầu khám phá! Giai đoạn này, thường gọi là Phân tích Dữ liệu Khám phá (EDA), có lẽ là bước quan trọng nhất trong một dự án dữ liệu. Những hiểu biết thu được từ EDA sẽ ảnh hưởng đến mọi thứ về sau.

Ví dụ, một trong những bước bắt buộc trong EDA là kiểm tra hình dạng của các phân phối. Xác định đúng hình dạng sẽ chi phối nhiều quyết định sau này trong dự án như:

  • Các bước tiền xử lý tiếp theo
  • Có nên phát hiện ngoại lệ và có thể là loại bỏ hay không
  • Các bước biến đổi hoặc chuẩn hóa đặc trưng
  • Lựa chọn đặc trưng
  • Lựa chọn thuật toán

v.v. Mặc dù có thể dùng biểu đồ để làm việc này, bạn cần những thước đo đáng tin cậy hơn để định lượng các đặc trưng của phân phối. Hai thước đo như vậy là độ lệch (skewness)độ nhọn (kurtosis). Bạn có thể dùng chúng để đánh giá mức độ tương đồng giữa các phân phối của mình với phân phối chuẩn hoàn hảo.

Khi đọc xong bài viết này, bạn sẽ nắm rõ:

  • Độ lệch và độ nhọn là gì
  • Các loại độ lệch và độ nhọn
  • Ảnh hưởng của độ lệch và độ nhọn lên các mô hình máy học
  • Cách tính độ lệch và độ nhọn trong Python thủ công và bằng các gói bên thứ ba
  • Trực quan hóa phân phối để kiểm chứng điểm số độ lệch và độ nhọn (phần toàn diện và thú vị)

Bắt đầu thôi!

Độ lệch (Skewness) là gì?

Ta thấy phân phối chuẩn ở khắp nơi: số đo cơ thể người, khối lượng vật thể, điểm IQ, kết quả kiểm tra, hay thậm chí trong phòng gym:

Hình ảnh máy tạ trong phòng gym. Các lỗ cắm chốt trên tạ collectively tạo thành hình dạng phân phối chuẩn do sử dụng quá nhiều trong thời gian dài.

Nguồn

Bên cạnh việc là phân phối ưa thích của tự nhiên, nó còn được hầu hết các thuật toán máy học yêu thích. Một số muốn nó để cải thiện và ổn định hiệu năng, một số thì hầu như từ chối hoạt động tốt với bất cứ thứ gì ngoài phân phối chuẩn (đang nói bạn đấy, các mô hình tuyến tính).

Vì vậy, để đáp ứng nhu cầu “chuẩn mực” của thuật toán, ta cần cách đo lường mức độ tương đồng (hoặc không) giữa các phân phối của mình với đường cong hình chuông hoàn hảo.

Đường cong hình chuông hoàn hảo của một phân phối chuẩn.

Bắt đầu với phần đuôi. Ở phân phối chuẩn hoàn hảo, hai đuôi bằng nhau về độ dài. Nhưng khi có sự bất đối xứng giữa hai đuôi, tạo cảm giác nghiêng, “bẹp” về một phía, ta nói phân phối đó bị lệch. Và đúng như bạn đoán, ta đo mức độ bất đối xứng này bằng độ lệch.

Các kiểu độ lệch khác nhau ở hai bên của một phân phối chuẩn không bị lệch.

Phân loại và đo độ lệch chính xác cung cấp góc nhìn về cách các giá trị phân tán quanh trung bình và ảnh hưởng đến việc chọn kỹ thuật thống kê cũng như biến đổi dữ liệu. Ví dụ, những phân phối bị lệch mạnh có thể hưởng lợi từ các kỹ thuật chuẩn hóa hoặc tỷ lệ hóa để làm chúng giống phân phối chuẩn hơn, hỗ trợ hiệu năng mô hình.

Các loại độ lệch

Có ba loại độ lệch: dương, âm và bằng không.

Bắt đầu với loại cuối. Một phân phối có độ lệch bằng không có các đặc điểm sau:

  • Phân phối đối xứng với các giá trị tập trung đều quanh trung bình.
  • Không nghiêng, không lệch hay đuôi về bất kỳ phía nào.
  • Trung bình, trung vị và mode đều ở cùng một điểm trung tâm.

Một phân phối chuẩn (độ lệch bằng không) với trung bình, trung vị và mode thẳng hàng.

Trong thực tế, trung bình, trung vị và mode có thể không chồng khít hoàn hảo. Chúng có thể hơi lệch nhau nhưng khác biệt thường quá nhỏ để đáng kể.

Trong một phân phối có độ lệch dương (lệch phải):

  • Đuôi bên phải dài hoặc “béo” hơn bên trái.
  • Trung bình lớn hơn trung vị, và mode nhỏ hơn cả trung bình lẫn trung vị.
  • Các giá trị thấp tập trung ở “đỉnh đồi” của phân phối, còn các giá trị cực trị nằm ở đuôi phải dài.
  • Còn gọi là phân phối lệch phải.

Phân phối lệch phải với chú thích trung bình, trung vị và mode.

Trong một phân phối có độ lệch âm (lệch trái):

  • Đuôi bên trái dài hoặc “béo” hơn bên phải.
  • Trung bình nhỏ hơn trung vị, và mode lớn hơn cả trung bình lẫn trung vị.
  • Các giá trị cao tập trung ở “đỉnh đồi” của phân phối, còn các giá trị cực trị nằm ở đuôi trái dài.
  • Còn gọi là phân phối lệch trái.

Phân phối lệch trái với chú thích trung bình, trung vị và mode

Để dễ nhớ sự khác biệt giữa lệch dương và lệch âm, hãy nghĩ thế này: nếu bạn muốn tăng trung bình của một phân phối, bạn nên thêm vào các giá trị cao hơn trung bình nhiều. Để giảm trung bình, làm ngược lại — thêm các giá trị thấp hơn trung bình nhiều. Vậy nên, nếu phần lớn các giá trị cực trị lớn hơn trung bình, độ lệch sẽ dương vì chúng làm tăng trung bình. Nếu phần lớn giá trị cực trị nhỏ hơn trung bình, độ lệch sẽ âm vì chúng làm giảm trung bình.

Cách tính độ lệch trong Python

Có nhiều cách tính độ lệch, nhưng đơn giản nhất là hệ số độ lệch thứ hai của Pearson, còn gọi là độ lệch theo trung vị.

image.png

Hãy hiện thực công thức này thủ công trong Python:

import numpy as np
import pandas as pd
import seaborn as sns

# Example dataset
diamonds = sns.load_dataset("diamonds")
diamond_prices = diamonds["price"]

mean_price = diamond_prices.mean()
median_price = diamond_prices.median()
std = diamond_prices.std()

skewness = (3 * (mean_price - median_price)) / std

>>> print(
   f"The Pierson's second skewness score of diamond prices distribution is {skewness:.5f}"
)

The Pierson's second skewness score of diamond prices distribution is 1.15189

Một công thức khác chịu ảnh hưởng lớn từ các công trình của Karl Pearson là công thức dựa trên moment để xấp xỉ độ lệch. Nó đáng tin cậy hơn và được cho bởi:

Công thức khác để tính độ lệch bằng các moment

Trong đó:

  • n là số lượng giá trị trong một phân phối
  • x_i biểu thị từng điểm dữ liệu

Hãy hiện thực nó trong Python nữa:

def moment_based_skew(distribution):
   n = len(distribution)
   mean = np.mean(distribution)
   std = np.std(distribution)

   # Divide the formula into two parts
   first_part = n / ((n - 1) * (n - 2))
   second_part = np.sum(((distribution - mean) / std) ** 3)

   skewness = first_part * second_part

   return skewness

>>> moment_based_skew(diamond_prices)
1.618440289857168

Nếu bạn không muốn tự tính (giống tôi), bạn có thể dùng phương thức dựng sẵn từ pandas hoặc scipy:

# Pandas version
diamond_prices.skew()
1.618395283383529

# SciPy version
from scipy.stats import skew

skew(diamond_prices)
1.6183502776053016

Mặc dù các công thức xấp xỉ độ lệch trả về điểm số khác nhau, khác biệt của chúng quá nhỏ để có ý nghĩa hoặc làm thay đổi cách phân loại độ lệch. Chẳng hạn, tất cả phương pháp hôm nay dùng các công thức khác nhau bên dưới, nhưng kết quả rất gần nhau.

Khi đã tính được độ lệch, bạn có thể phân loại mức độ lệch:

  • (-0.5, 0.5) — thấp hoặc xấp xỉ đối xứng.
  • (-1, -0.5) U (0.5, 1) — lệch vừa.
  • Ngoài -1 và 1 — lệch mạnh.

Độ nhọn (Kurtosis) là gì và các loại của nó?

Trong khi độ lệch tập trung vào độ lan rộng (đuôi) của phân phối chuẩn, độ nhọn tập trung nhiều hơn vào chiều cao. Nó cho biết phân phối chuẩn (hoặc giống chuẩn) của ta nhọn hay phẳng đến mức nào. Thuật ngữ này, có nghĩa là cong hoặc vòm trong tiếng Hy Lạp, lần đầu được đặt ra bởi, không ngạc nhiên, nhà toán học người Anh Karl Pearson (người dành cả đời nghiên cứu các phân phối xác suất).

Độ nhọn cao cho thấy:

  • Đỉnh nhọn ở trung tâm phân phối.
  • Nhiều giá trị tập trung quanh trung bình hơn so với phân phối chuẩn.
  • Đuôi nặng hơn do tập trung nhiều giá trị cực trị hoặc ngoại lệ ở đuôi.
  • Khả năng xảy ra các sự kiện cực đoan lớn hơn.

Ngược lại, độ nhọn thấp cho thấy:

  • Đỉnh phẳng.
  • Ít giá trị tập trung quanh trung bình hơn, nhưng vẫn nhiều hơn phân phối chuẩn.
  • Đuôi nhẹ hơn.
  • Khả năng xảy ra sự kiện cực đoan thấp hơn.

Tùy theo mức độ, các phân phối có ba loại độ nhọn:

  1. Mesokurtic (kurtosis = 3, excess kurtosis = 0): phân phối chuẩn hoàn hảo hoặc rất gần với nó.
  2. Leptokurtic (kurtosis > 3, excess kurtosis > 0): đỉnh nhọn, đuôi nặng
  3. Platykurtic (kurtosis < 3, excess kurtosis < 0): đỉnh phẳng, đuôi nhẹ

Ba kiểu phân phối: leptokurtic (độ nhọn cao), mesokurtic (không lệch so với chuẩn) và platykurtic (độ nhọn thấp)

Lưu ý rằng ở đây, độ nhọn dư (excess kurtosis) được định nghĩa là kurtosis - 3, coi độ nhọn của phân phối chuẩn là 0. Cách này khiến điểm số độ nhọn dễ diễn giải hơn.

Cách tính độ nhọn trong Python

Bạn có thể tính độ nhọn trong Python tương tự như độ lệch bằng pandas hoặc SciPy:

from scipy.stats import kurtosis

kurtosis(diamond_prices)
2.177382669056634

Pandas cung cấp hai hàm cho độ nhọn: kurtkurtosis. Cái đầu dành riêng cho Series của Pandas, còn cái sau có thể dùng trên DataFrame.

diamond_prices.kurt()
2.17769575924869

# Select numeric features and calculate kurtosis
diamonds.select_dtypes(include="number").kurtosis()
carat     1.256635
depth     5.739415
table     2.801857
price     2.177696
x        -0.618161
y        91.214557
z        47.086619
dtype: float64

Một lần nữa, các con số khác nhau do pandas và SciPy dùng công thức khác nhau.

Nếu bạn muốn tính thủ công độ nhọn, có thể dùng công thức sau:

Công thức tính độ nhọn bằng các moment, chịu ảnh hưởng bởi Karl Pearson

Trong đó:

  • n là số quan sát trong tập dữ liệu
  • x_i biểu thị từng điểm dữ liệu riêng lẻ

Ta sẽ hiện thực công thức trong một hàm như trước:

def moment_based_kurtosis(distribution):
   n = len(distribution)
   mean = np.mean(distribution)
   std = np.std(distribution)

   kurtosis = (1 / n) * sum(((distribution - mean) / std) ** 4) - 3

   return kurtosis

>>> moment_based_kurtosis(diamond_prices)
2.1773826690576463

Và ta thấy giá kim cương có độ nhọn dư là 2.18, nghĩa là nếu vẽ phân phối, nó sẽ có đỉnh nhọn hơn phân phối chuẩn.

Vậy hãy cùng vẽ!

Trực quan hóa độ lệch và độ nhọn trong Python

Một trong những biểu đồ tốt nhất để nhìn hình dạng và do đó cả độ lệch lẫn độ nhọn của phân phối là biểu đồ ước lượng mật độ nhân (KDE). Nó có sẵn trong Seaborn:

import matplotlib.pyplot as plt

sns.kdeplot(diamond_prices)

plt.title("KDE plot of diamond prices")
plt.xlabel("Price ($)")

Biểu đồ KDE của giá kim cương

Biểu đồ này phù hợp với các con số ta đã thấy: phân phối có đuôi phải dài, biểu thị độ lệch dương, và có đỉnh rất nhọn, tương ứng với độ nhọn cao.

KDE không phải lựa chọn duy nhất để xem hình dạng. Ta cũng có thể dùng biểu đồ tần suất (histogram):

sns.histplot(diamonds["carat"])

plt.xlabel("Carat")
plt.title("A histogram of the carat of diamonds")

Biểu đồ tần suất carat của kim cương

Nhược điểm của histogram là bạn phải tự chọn số lượng “bins” (số cột). Ở đây có quá nhiều cột gây nhiễu thị giác — ta không thể xác định rõ hình dạng. Vậy hãy giảm số bins:

sns.histplot(diamonds["carat"], bins=25)

plt.xlabel("Carat")
plt.title("A histogram of the carat of diamonds")

Biểu đồ tần suất carat của kim cương với ít bins hơn

Giờ hình dạng rõ ràng hơn nhưng vẫn có thể cải thiện. Bằng cách đặt kde=True trong histplot, ta có thể vẽ thêm KDE chồng lên các cột:

sns.histplot(diamonds["carat"], bins=25, kde=True)

plt.xlabel("Carat")
plt.title("A histogram of the carat of diamonds")

Histogram chồng lên KDE của carat kim cương

Đường KDE chồng lên trông răng cưa, không phải đường cong mượt giúp ta thấy hình dạng tổng quát. Lý do là phân phối carat vốn dĩ nhiều gai và xa phân phối chuẩn.

Tuy nhiên, ta có thể giảm độ nhạy của KDE với các dao động này bằng cách điều chỉnh băng thông. Làm điều này bằng tham số bw_adjust, mặc định là 1:

# Change the bandwidth from 1 to 3
sns.kdeplot(diamonds["carat"], bw_adjust=3, color="red")

plt.title("KDE of diamond carats");

KDE của carat kim cương với điều chỉnh băng thông cao hơn

Phiên bản này ít gai hơn nhiều so với KDE chồng lên. Để điều chỉnh băng thông KDE khi dùng histogram chồng KDE, bạn có thể dùng tham số kde_kws:

ax = sns.histplot(
   diamonds["carat"],
   kde=True,
   kde_kws=dict(bw_adjust=3),
   bins=25,
)

plt.title("An overlaid histogram of diamond carats");

Histogram chồng KDE với băng thông đã được điều chỉnh.

kde_kws chấp nhận mọi tham số mà hàm kdeplot hỗ trợ để điều khiển việc tính KDE.

Một mẹo khi vẽ KDE là loại bỏ mọi thứ ngoại trừ đường KDE. Vì mục đích chính của KDE là xem hình dạng phân phối, các chi tiết khác như vạch chia trục, khung viền và nhãn đôi khi không cần thiết:

sns.kdeplot(diamond_prices, color="red")

# Remove the spine from three sides
sns.despine(top=True, right=True, left=True)

# Remove the ticks and ticklabels
plt.xticks([])
plt.yticks([])
plt.ylabel("")
plt.xlabel("")

# Set a title
plt.title("Diamond prices", fontdict=dict(fontsize=20));

Biểu đồ KDE chỉ giữ lại đường KDE và tiêu đề.

Biểu đồ này gọn gàng hơn nhiều. Bạn có thể cải thiện thêm bằng cách thêm các đường biểu thị vị trí trung bình, trung vị và mode:

sns.kdeplot(diamond_prices, color="red")

sns.despine(top=True, right=True, left=True)
plt.xticks([])
plt.yticks([])
plt.ylabel("")
plt.xlabel("")
plt.title("Diamond prices", fontdict=dict(fontsize=20))

# Find the mean, median, mode
mean_price = diamonds["price"].mean()
median_price = diamonds["price"].median()
mode_price = diamonds["price"].mode().squeeze()

# Add vertical lines at the position of mean, median, mode
plt.axvline(mean_price, label="Mean")
plt.axvline(median_price, color="black", label="Median")
plt.axvline(mode_price, color="green", label="Mode")

plt.legend();

Biểu đồ KDE chỉ giữ đường KDE, tiêu đề và chú thích trung bình, trung vị, mode.

Biểu đồ này kiểm chứng những gì ta đã bàn ở phần các loại độ lệch: trong một phân phối lệch dương, trung bình cao hơn trung vị, và mode thấp hơn cả trung bình lẫn trung vị.

Kết luận

Độ lệch và độ nhọn, thường bị bỏ qua trong EDA, lại hé lộ những hiểu biết quan trọng về bản chất của các phân phối.

Độ lệch cho biết xu hướng nghiêng của dữ liệu, lệch trái hay phải, bộc lộ sự bất đối xứng (nếu có). Lệch dương nghĩa là đuôi kéo dài về bên phải, còn lệch âm thì ngược lại.

Độ nhọn nói về đỉnh và đuôi. Độ nhọn cao làm đỉnh nhọn hơn và đuôi nặng hơn, trong khi độ nhọn thấp khiến dữ liệu dàn trải, đuôi nhẹ hơn.

Nếu bạn muốn tìm hiểu sâu hơn về độ lệch và độ nhọn, bạn có thể xem các khóa học phân tích định lượng xuất sắc do các chuyên gia trong ngành giảng dạy trên DataCamp:


Bex Tuychiev's photo
Author
Bex Tuychiev
LinkedIn

Tôi là người sáng tạo nội dung về khoa học dữ liệu với hơn 2 năm kinh nghiệm và là một trong những tài khoản có lượng theo dõi lớn nhất trên Medium. Tôi thích viết các bài chuyên sâu về AI và ML với chút giọng điệu mỉa mai, vì bạn cũng phải làm gì đó để chúng bớt nhàm chán. Tôi đã xuất bản hơn 130 bài viết và một khóa học trên DataCamp, và đang ấp ủ thêm một khóa nữa. Nội dung của tôi đã tiếp cận hơn 5 triệu lượt xem, trong đó có 20 nghìn người trở thành người theo dõi trên cả Medium và LinkedIn. 

Chủ đề

Tìm hiểu thêm! 

Courses

Nhập môn Quản trị Rủi ro Danh mục bằng Python

4 giờ
29K
Xem chi tiếtRight Arrow
Bắt đầu khóa học
Xem thêmRight Arrow