MissForest bằng Python

Có lẽ giai đoạn đòi hỏi khắt khe nhất trong nghiên cứu về khoa học dữ liệu hoặc vấn đề học máy là giai đoạn tiền xử lý dữ liệu, nhằm mục đích cuối cùng là tạo ra một tập dữ liệu hữu ích. Nếu việc xử lý các mô hình học máy tuyệt vời là điểm hấp dẫn của Achilles, thì việc xử lý trước dữ liệu sẽ là kẻ bị nguyền rủa của Sisyphus

Nguồn. Wikipedia

Bộ dữ liệu thường chứa dữ liệu bị thiếu. Lý do thường khác nhau tùy thuộc vào bản chất của bộ dữ liệu, vấn đề hoặc cách nó được thu thập. Nếu nó được lấy từ một cuộc khảo sát, một số câu hỏi có thể không được trả lời. Hoặc, nếu nó được thu thập từ một luồng dữ liệu, thì có thể có sự cố với luồng trong một số trường hợp. Nếu dữ liệu được lấy từ một hệ thống, một số tính năng có thể không có dữ liệu trong một số trường hợp, v.v.

Chúng ta phải giải quyết những giá trị còn thiếu. Bởi vì các giá trị bị thiếu có ảnh hưởng trực tiếp đến sự thành công của mô hình. Ngoài ra, nhiều mô hình máy học không hoạt động với bộ dữ liệu chứa các giá trị bị thiếu

Việc phân phối các giá trị bị thiếu có thể là ngẫu nhiên hoặc có thể theo một mẫu nhất định. Trong một số trường hợp, các giá trị bị thiếu thực sự có thể là một dữ liệu duy nhất khác kể một câu chuyện. Do đó, cấu trúc và mô hình của chúng nên được khám phá và, nếu có thể truy cập được, kết hợp với kiến ​​thức miền. Ví dụ: giả sử rằng câu hỏi đầu tiên của cuộc khảo sát là "Bạn có việc làm không?", và câu hỏi thứ hai là "Mức lương của bạn là bao nhiêu?". Người tham gia chỉ có thể trả lời câu hỏi thứ hai nếu câu trả lời cho câu hỏi đầu tiên là “có”, nếu không, ứng dụng sẽ không cho phép người đó trả lời. Trong trường hợp này, dữ liệu bị thiếu trong cột lương sẽ không ngẫu nhiên, sẽ theo một khuôn mẫu

Thiếu mẫu dữ liệu

Chúng ta có thể phân loại dữ liệu bị thiếu được phân phối theo cấu trúc nào. Chúng ta có thể liệt kê 3 loại khái quát. MCAR, MAR và MNAR

MCAR. Mất tích hoàn toàn ngẫu nhiên

Xác suất thiếu dữ liệu là như nhau đối với mọi trường hợp và không liên quan đến cả tham số quan sát được và không quan sát được. Trong trường hợp này, thông tin bị mất do thiếu giá trị, tuy nhiên, nó không làm tăng thêm độ phức tạp cho mô hình. Hãy xem xét một điều khiển TV sắp hết pin. Đôi khi nó sẽ thay đổi kênh, đôi khi nó sẽ không. Khi nó không hoạt động, nó chỉ là xui xẻo

Nếu dữ liệu bị thiếu không thể điền vào, nó có thể bị xóa. Bởi vì nó không làm tăng thêm độ phức tạp mặc dù thông tin bị mất

tháng ba. Mất tích ngẫu nhiên

Sự mất tích chỉ phụ thuộc vào dữ liệu mà chúng ta thực sự quan sát được. Xác suất mất tích là như nhau trong các nhóm duy nhất, nhưng khác nhau giữa các nhóm khác nhau. Hãy tưởng tượng rằng chúng tôi vô tình làm hỏng điều khiển từ xa nói trên. Các phím bên dưới bị hỏng. Xác suất không hoạt động giữa các phím trên và dưới sẽ khác nhau. Tuy nhiên, các khóa trong các nhóm vẫn có tính ngẫu nhiên

Vì các nhóm chỉ ra cùng một hành vi trong chính họ và hành vi khác nhau giữa các nhóm khác, nên có thể áp dụng quy nạp

MNAR. Mất tích không phải ngẫu nhiên

Có một cơ chế đằng sau sự mất tích. Nó phụ thuộc vào dữ liệu không quan sát được. Trong trường hợp này, tốt hơn là làm việc trên tập dữ liệu và thu thập dữ liệu mới để khắc phục MNAR

phát hiện

Tôi sẽ sử dụng tập dữ liệu Titanic cổ điển để minh họa các cách khám phá các giá trị còn thiếu trong tập dữ liệu

df.isnull[]
#True if the cell is missing.

Tổng số giá trị bị thiếu cho mỗi tính năng

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64

Hình dung

Chúng ta có thể sử dụng các kỹ thuật trực quan để khám phá các giá trị còn thiếu. Bản đồ nhiệt phù hợp để trực quan hóa. Mỗi dòng biểu thị dữ liệu bị thiếu trong một hàng

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']

Chúng tôi cũng có thể sử dụng thư viện missingno cho việc này

import missingno as msno
msno.matrix[data]

Chúng ta cũng có thể thay đổi thứ tự của các hàng

msno.matrix[df.sort_values['Ticket']]

Phương pháp xử lý

Dữ liệu bị thiếu có thể được xử lý bằng nhiều phương pháp khác nhau. Các phương pháp này có thể được nhóm lại như sau;

  • Xóa cột hoặc hàng
  • Quy nạp - điền vào một giá trị
  • Tạo một tính năng mới
  • Sử dụng một công cụ ước tính

Loại bỏ

Giải pháp đơn giản nhưng kém hiệu quả nhất. Nếu phần lớn cột hoặc hàng bị thiếu [phải có quá nhiều. ], chúng tôi có thể xem xét xóa nó. Hãy nhớ rằng, xóa một cột tệ hơn nhiều so với xóa một hàng vì chúng ta có thể mất nhiều thông tin vì cột là một tính năng

#removing all of the missing rows
print[df.shape]
df.dropna[inplace=True]
print[df.shape]
-------
[891, 12]
[183, 12]

Như bạn có thể thấy, có quá nhiều dòng đã bị xóa

#removing columns with nan values
print[df.shape]
df.dropna[axis='columns',inplace=True]
print[df.shape]
-----------
[891, 12]
[891, 9]

Tuổi, cabin và các cột bắt tay được loại bỏ

Một cách khác là đặt giá trị ngưỡng để xóa một số cột hoặc hàng. Ví dụ: chúng tôi có thể xóa các cột nếu tỷ lệ cột bị thiếu lớn hơn 75%

#removing columns if missing val ratio is bigger than .75
df = df.loc[:, df.isnull[].mean[] < .75]
print[df.shape]
---------
[891, 11]

Hoặc, chúng tôi có thể xóa các hàng bằng cách đưa ra số lượng giá trị không thiếu tối thiểu. Lần này, một hàng phải được lấp đầy ít nhất 90%, nếu không, nó sẽ bị xóa

________số 8

quy tội

Chúng ta có thể thay thế các giá trị còn thiếu bằng một giá trị khác. Điều này có thể được áp dụng theo những cách khác nhau cho các giá trị số và phân loại

Một giá trị không đổi có thể được gán cho các tính năng số. Thông tin về giá trị không đổi sẽ đến từ miền. Ví dụ: chúng tôi chỉ có thể đặt các giá trị bị thiếu trong cột Tuổi là 18 nếu kiến ​​thức miền hỗ trợ điều đó

df["Age"].fillna[18,inplace=True]

Tương tự, chúng ta có thể gán một nhóm danh mục mới trong các tính năng phân loại. Ví dụ: chúng ta có thể thay thế dữ liệu bị thiếu bằng danh mục mới là “Thiếu”

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
0

Sử dụng các giá trị tổng hợp là một tùy chọn khác. Giá trị trung bình của một tính năng số có thể được thay thế bằng Nans. Sử dụng giá trị trung bình là một phương pháp đơn giản cho các tập dữ liệu nhỏ và có thể hoạt động tốt, nhưng nó không hoạt động tốt trên các tập dữ liệu lớn. Nếu các ngoại lệ tồn tại trong tính năng, nó có thể ảnh hưởng đến chất lượng của mô hình nói chung, vì giá trị trung bình sẽ là một giá trị sai lệch. Vì những lý do này, độ lệch của tính năng nên được kiểm tra trước

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
1

Nếu tính năng bị sai lệch, giá trị trung bình có thể được sử dụng thay cho giá trị trung bình

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
2

Tương tự, các tính năng phân loại có thể được gán với giá trị chế độ. Nó cũng được áp dụng cho các tính năng số. Nếu tính năng này không cân bằng [vấn đề mất cân bằng lớp], thì việc điền các giá trị còn thiếu bằng chế độ có thể gây sai lệch cho dữ liệu

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
3

Một phương pháp khác có thể được sử dụng cho các tính năng phân loại là tạo một tính năng mới cho dữ liệu bị thiếu. Tính năng mới này có thể là một giá trị logic đúng nếu dữ liệu tồn tại trong tính năng được tham chiếu, nếu không, nó có thể được đặt thành sai. Do đó, thông tin được cung cấp bởi dữ liệu bị thiếu không bị mất

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
4

Dữ liệu bị thiếu có thể được lấp đầy bằng dữ liệu ở hàng trước hoặc hàng tiếp theo. Có thể áp dụng phương pháp này nếu có mối quan hệ tuần tự giữa các quan sát

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
5

Máy Tính Đơn Giản

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
6

Đó là một lớp máy tính tự động của sklearn. Các thông số nó cần;

giá trị bị mất. int, float, str, np. nan, Không, mặc định=np. nan

Các loại giá trị bị thiếu. Trong một khung dữ liệu gấu trúc, các loại của chúng là np. nan

chiến lược. str, mặc định=’có nghĩa là’

{‘mean’, ‘median’, ’most_frequent’, ’constant’}

Chiến lược quy nạp

fill_value. str hoặc số, default=None

Giá trị không đổi sẽ được sử dụng nếu chiến lược được đặt là không đổi

sao chép. bool, mặc định=True

Máy tính tạo một bản sao của X đã cho

add_indicator. bool, mặc định=Sai

Nếu được bật, một công cụ ước tính có thể giải thích cho sự thiếu sót mặc dù đã quy nạp

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
7

nội suy

Nội suy là một kỹ thuật toán học để ước tính dữ liệu bị thiếu trong một chuỗi. Nó lấy các quan sát và điều chỉnh một chức năng cho chúng. Không gian phạm vi của chức năng rộng hơn khi dữ liệu. Đó là lý do tại sao nó được gọi là phép nội suy, nếu chúng ta đang ước tính dữ liệu xa hơn từ phạm vi thì đó sẽ là phép ngoại suy. Nội suy được sử dụng đặc biệt trong các bài toán về chuỗi thời gian vì nó có khả năng lấp đầy các giá trị còn thiếu bằng các giá trị trước đó

Nguồn nội suy so với nguồn ngoại suy. thống kê
df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
8

phương pháp. str, mặc định = 'tuyến tính'

{ 'tuyến tính', 'thời gian', 'chỉ số', 'giá trị', 'pad', 'gần nhất', 'không', 'tuyến tính', 'bậc hai', 'khối', 'spline', 'barycentric', '

Nội suy tuyến tính là phương pháp mặc định. Nó kết nối các dấu chấm theo một đường thẳng theo thứ tự và ước tính giá trị chưa biết theo thứ tự như trước đó. Nó không sử dụng các chỉ mục khi kết nối các dấu chấm. Nó sắp xếp các số theo giá trị của chúng. Nội suy thời gian là như nhau nếu khoảng thời gian được đặt bằng nhau, nó dựa trên các khoảng thời gian

Chỉ mục và giá trị sử dụng giá trị thực của chỉ mục. Có thể được áp dụng cho dữ liệu tuần tự. Pad sử dụng dữ liệu không thiếu trước đó hoặc tiếp theo

Gần nhất là rõ ràng. Zero, slinear, bậc hai và bậc ba lần lượt là bậc 0, bậc nhất, bậc hai hoặc bậc ba của phép nội suy spline

Barycentric là một biến thể của phép nội suy đa thức. Nó hành động đối với vấn đề như một trường hợp đặc biệt của phép nội suy hàm hữu tỷ. Chúng tôi đã sử dụng các đường thẳng trong phép nội suy tuyến tính. Nhưng nếu dữ liệu không phải là tuyến tính mà là đa thức, thì chúng ta nên sử dụng phép nội suy đa thức. Krogh là một phương pháp nội suy đa thức đặc biệt khác. Nếu chúng ta có nhiều điểm thì phép nội suy đa thức có thể gặp vấn đề, trong trường hợp này, bạn nên đi các bậc cao hơn nhưng lúc này sẽ xảy ra sự cố dao động. Đó là nơi mà piecewise_polynomial phát huy tác dụng. from_derivatives là một phương thức đặc biệt của piecewise_polynomials

nội suy đa thức. Nguồn. Wikipedia

Một spline là một trường hợp đặc biệt của đa thức từng phần. Chúng là tập hợp các đa thức bậc thấp. Vì vậy, thay vì đưa ra đa thức bậc cao, bạn có thể sử dụng 9 đa thức bậc thấp chẳng hạn. Các phương pháp chip, anima, và cube spline là những trường hợp đặc biệt của phép nội suy spline

spline. Nguồn. Wikipedia

trục. {0 hoặc 'chỉ mục, 1 hoặc 'cột, Không}, mặc định = Không

giới hạn. int, tùy chọn [>0]

Bạn có thể đặt giới hạn tối đa để điền liên tục

giới hạn_hướng. {'tiến tới','lùi lại','cả hai'}, mặc định=Không

Nếu phương thức được chọn là ‘pad’, ‘ffil’ => hướng phải chuyển tiếp. Mặt khác, phương pháp được chọn là 'chèn lấp', 'brill' và hướng phải quay ngược

giới hạn_khu vực. {Không, 'bên trong', 'bên ngoài'}, mặc định=Không

nội bộ. suy ra; . ngoại suy

KNN. K-Hàng xóm gần nhất

KNN là một phương pháp học máy có giám sát được sử dụng cho các vấn đề phân loại và hồi quy. Nó tính toán khoảng cách giữa các điểm dữ liệu [hầu hết thời gian là Euclide] và các nhóm gần nhau. Các tính năng số phải được chia tỷ lệ và các tính năng phân loại phải được chuyển đổi trước khi áp dụng quy nạp KNN

df.isnull[].sum[]-----------
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
9

Các mô hình dự đoán khác

Hồi quy tuyến tính hoặc logistic có thể được áp dụng để điền vào các tính năng số và phân loại tương ứng. Một mô hình được đào tạo với tập hợp con của khung dữ liệu chứa các giá trị không bị thiếu. Mô hình này dự đoán kết quả của một tập hợp con khác của khung dữ liệu chứa các giá trị bị thiếu

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
0

Bất kỳ mô hình học máy nào cũng có thể được triển khai với logic trên

Hoa hậu rừng

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
1

Đó là một phép gán dựa trên máy học sử dụng mô hình Rừng ngẫu nhiên. Không quan tâm dữ liệu có phân loại hay không và bạn không cần điều chỉnh dữ liệu như đã làm với KNN. Đó là một cách tiếp cận lặp đi lặp lại, tiếp tục trở nên tốt hơn sau mỗi lần lặp lại

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
2

Bạn có thể đạt được các thông số ở đây

CHUỘT. Tính toán đa biến bằng phương trình chuỗi

Trong phương pháp này, chúng tôi lập mô hình tính năng bị thiếu dữ liệu so với các tính năng còn lại bằng cách sử dụng các công cụ ước tính khác nhau. Các tập hợp con ngẫu nhiên của dữ liệu được đưa vào nhiều mô hình và kết quả trung bình được trả về là kết quả

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
3

Lặp đi lặp lại

Máy tính đa biến của Sklearn

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
4

ước lượng. đối tượng ước tính, default=BayesianRidge[]

Cung cấp một công cụ ước tính cho máy tính

giá trị bị mất. int hoặc np. nan, mặc định=np. nan

Loại giá trị bị thiếu trong tập dữ liệu

sample_posterior. bool, mặc định=Sai

Khi mô hình tạo ra một phân phối đầu ra [thay vì một dự đoán duy nhất], hãy đặt True. Nhiều bộ dữ liệu bị tranh chấp được lấy trong quy trình và lấy mẫu từ chúng

max_iter. int, mặc định=10

Vòng loại tối đa

tol. thả nổi, mặc định=1e-3

Một giá trị dung sai có thể được xác định để dừng

n_gần_tính_năng. int, mặc định=Không

Không phải tất cả các tính năng đều được sử dụng, thay vào đó, bạn có thể xác định một tập hợp con của chúng. Các tính năng được chọn theo hệ số tương quan tuyệt đối của chúng giữa mỗi cặp

initial_strategy. str, mặc định=’có nghĩa là’

{‘mean’, ‘median’, ‘most_frequent’, ‘constant’}

Tương tự với SimpleImuter

quy định_thứ tự. str, default='tăng dần'

{'tăng dần', 'giảm dần', 'roman', 'tiếng Ả Rập', 'ngẫu nhiên'}

Thứ tự của các tính năng được điền. 'tăng dần'; . 'roman' từ trái sang phải và 'tiếng Ả Rập' từ phải sang trái

bỏ qua_đầy đủ. bool, mặc định=Sai

Đặt nó thành True nếu nhiều tính năng không có giá trị bị thiếu để lưu tính toán

min_value. float hoặc mảng hình dạng [n_features,], default=np. inf

Bạn có thể xác định giá trị tối thiểu có thể để quy

giá trị tối đa. float hoặc mảng hình dạng [n_features,], default=np. ing

Logic tương tự như trên

add_indicator. bool, mặc định=Sai

Tương tự với SimpleImuter

sns.heatmap[df.isnull[],yticklabels=False,cbar=False,cmap='YlGnBu']
5Kết luận

Để mô hình học máy hoạt động bình thường và tăng độ chính xác, bộ dữ liệu phải được tối ưu hóa trước. Công việc tiền xử lý này thường là phần dài và khó khăn trong toàn bộ công việc, và đôi khi còn quan trọng hơn cả bản thân mô hình. Có thể có các giá trị bị thiếu trong tập dữ liệu vì nhiều lý do. Nhiều mô hình học máy cũng bị lỗi hoặc không hoạt động bình thường trong các tập dữ liệu bị thiếu giá trị. Vì vậy, chúng ta cần xử lý các giá trị còn thiếu. Trong blog này, tôi đã cố gắng tóm tắt những phương pháp bạn có thể sử dụng để xử lý các giá trị bị thiếu

Đọc thêm…

Danh mục chi tiết về giảm kích thước

Nhiều phương pháp giảm kích thước được giải thích bằng ngôn ngữ Python

vừa phải. com

Các phương pháp lựa chọn tính năng được sử dụng nhiều nhất

Giải thích về các phương pháp lựa chọn tính năng thường được sử dụng trong học máy

đối với dev. com

Các kỹ thuật chuyển đổi tính năng là gì?

Chuyến tham quan qua các kỹ thuật chuyển đổi tính năng

vừa phải. com

Outliers và Anomalies là gì?

Đi sâu vào thế giới dị thường

con trăn. tiếng Anh đơn giản. io

Người giới thiệu

https. // vi. wikipedia. org/wiki/Nội suy

https. //scikit-học. org/ổn định/mô-đun/được tạo/sklearn. quy tội. Máy Tính Đơn Giản. html

https. //scikit-học. org/ổn định/mô-đun/được tạo/sklearn. quy tội. Lặp đi lặp lại. html

https. //scikit-học. org/ổn định/mô-đun/được tạo/sklearn. quy tội. KNNMáy tính. html

https. //www. phân tíchvidhya. com/blog/2021/10/how-to-deal-with-missing-data-using-python/

Thêm nội dung tại PlainEnglish. io. Đăng ký nhận bản tin hàng tuần miễn phí của chúng tôi. Theo dõi chúng tôi trên Twitter và LinkedIn. Tham gia cộng đồng của chúng tôi

MissForest là gì?

MissForest là một thuật toán gán dữ liệu dựa trên máy học khác hoạt động trên thuật toán Rừng ngẫu nhiên . Stekhoven và Buhlmann, những người tạo ra thuật toán, đã thực hiện một nghiên cứu vào năm 2011, trong đó các phương pháp quy nạp được so sánh trên các bộ dữ liệu với các giá trị bị thiếu được giới thiệu ngẫu nhiên.

MissForest có phải là quy nạp nhiều lần không?

Chúng tôi đề xuất và đánh giá một phương pháp quy nạp lặp lại [missForest] dựa trên một khu rừng ngẫu nhiên. Bằng cách tính trung bình trên nhiều cây hồi quy hoặc phân loại chưa được cắt tỉa, rừng ngẫu nhiên về bản chất tạo thành một sơ đồ quy nạp nhiều lần .

Random Forest có thể xử lý các giá trị bị thiếu trong Python không?

Có nhiều kỹ thuật quy nạp mà chúng tôi có thể sử dụng để xử lý các giá trị bị thiếu. Ví dụ, phương tiện quy nạp cho dữ liệu liên tục là vấn đề thường xuyên nhất trong trường hợp dữ liệu phân loại. Hoặc chúng ta có thể sử dụng các thuật toán máy học như KNN và Random Forests để giải quyết vấn đề thiếu dữ liệu .

Chức năng máy tính là gì?

Máy tính là công cụ ước tính được sử dụng để điền vào các giá trị còn thiếu trong bộ dữ liệu . Đối với các giá trị số, nó sử dụng giá trị trung bình, trung bình và hằng số. Đối với các giá trị phân loại, nó sử dụng giá trị không đổi và được sử dụng thường xuyên nhất. Bạn cũng có thể đào tạo mô hình của mình để dự đoán các nhãn bị thiếu.

Chủ Đề