4.10. Dự đoán Giá Nhà trên Kaggle

Trong phần trước, chúng tôi đã giới thiệu những công cụ cơ bản để xây dựng mạng học sâu và kiểm soát năng lực của nó thông qua việc giảm chiều dữ liệu, suy giảm trọng số và dropout. Giờ bạn đã sẵn sàng để ứng dụng tất cả những kiến thức này vào thực tiễn bằng cách tham gia một cuộc thi trên Kaggle. Dự đoán giá nhà là một bài toán tuyệt vời để bắt đầu: dữ liệu tương đối khái quát, không có cấu trúc cứng nhắc nên không đòi hỏi những mô hình đặc biệt như các bài toán có dữ liệu ảnh và âm thanh. Tập dữ liệu này được thu thập bởi Bart de Cock vào năm 2011 [DeCock, 2011], lớn hơn rất nhiều so với tập dữ liệu giá nhà Boston nổi tiếng của Harrison và Rubinfeld (1978). Nó có nhiều mẫu và đặc trưng hơn, chứa thông tin về giá nhà ở Ames, Indiana trong khoảng thời gian từ 2006-2010.

Trong mục này, chúng tôi sẽ hướng dẫn bạn một cách chi tiết các bước tiền xử lý dữ liệu, thiết kế mô hình, lựa chọn và điều chỉnh siêu tham số. Chúng tôi mong rằng thông qua việc thực hành, bạn sẽ có thể quan sát được tác động của việc kiểm soát năng lực mô hình, trích xuất đặc trưng, v.v. trong thực tiễn. Kinh nghiệm này rất quan trọng để bạn có được trực giác của một nhà khoa học dữ liệu.

4.10.1. Tải và Lưu trữ Bộ dữ liệu

Trong suốt cuốn sách chúng ta sẽ cần tải và thử nghiệm nhiều mô hình trên các tập dữ liệu khác nhau. Ta sẽ lập trình một số hàm tiện ích để hỗ trợ cho việc tải dữ liệu. Đầu tiên, ta cần khởi tạo một từ điển DATA_HUB nhằm ánh xạ một xâu ký tự đến đường dẫn (URL) với SHA-1 của tệp tại đường dẫn đó, trong đó SHA-1 dùng để xác minh tính toàn vẹn của tệp. Các tập dữ liệu này được lưu trữ trên trang DATA_URL.

import os
from mxnet import gluon
import zipfile
import tarfile

# Saved in the d2l package for later use
DATA_HUB = dict()

# Saved in the d2l package for later use
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'

Hàm download dưới đây tải tập dữ liệu có tên name từ đường dẫn tương ứng và lưu trữ nó tại bộ nhớ cục bộ (mặc định tại ../data). Nếu tệp trên đã tồn tại trong bộ nhớ đệm và SHA-1 của nó khớp với tệp trong DATA_HUB, tệp trong bộ nhớ đệm sẽ được sử dụng luôn mà không cần phải tải lại. Điều này nghĩa là bạn chỉ cần tải tập dữ liệu đúng một lần khi có kết nối mạng. Hàm download trả về tên của tệp được tải xuống.

# Saved in the d2l package for later use
def download(name, cache_dir='../data'):
    """Download a file inserted into DATA_HUB, return the local filename."""
    assert name in DATA_HUB, "%s doesn't exist" % name
    url, sha1 = DATA_HUB[name]
    d2l.mkdir_if_not_exist(cache_dir)
    return gluon.utils.download(url, cache_dir, sha1_hash=sha1)

Chúng ta cũng lập trình thêm hai hàm khác: một hàm để tải và giải nén tệp zip/tar, và hàm còn lại để tải tất cả các file từ DATA_HUB (chứa phần lớn các tập dữ liệu được sử dụng trong cuốn sách này) về bộ nhớ đệm. Bạn có thể sử dụng hàm thứ hai để tải tất cả các tập dữ liệu này trong cùng một lần tải nếu kết nối mạng của bạn chậm.

# Saved in the d2l package for later use
def download_extract(name, folder=None):
    """Download and extract a zip/tar file."""
    fname = download(name)
    base_dir = os.path.dirname(fname)
    data_dir, ext = os.path.splitext(fname)
    if ext == '.zip':
        fp = zipfile.ZipFile(fname, 'r')
    elif ext == '.tar' or ext == '.gz':
        fp = tarfile.open(fname, 'r')
    else:
        assert False, 'Only zip/tar files can be extracted'
    fp.extractall(base_dir)
    if folder:
        return base_dir + '/' + folder + '/'
    else:
        return data_dir + '/'

# Saved in the d2l package for later use
def download_all():
    """Download all files in the DATA_HUB"""
    for name in DATA_HUB:
        download(name)

4.10.2. Kaggle

Kaggle là một nền tảng phổ biến cho các cuộc thi học máy. Nó kết hợp dữ liệu, mã lập trình và người dùng cho cả mục đích hợp tác và thi thố. Mặc dù việc cạnh tranh trên bảng xếp hạng nhiều khi vượt khỏi tầm kiểm soát, ta không thể không nhắc đến sự khách quan mà nền tảng mang lại từ việc so sánh định lượng một cách công bằng và trực tiếp giữa phương pháp của bạn với các phương pháp của đối thủ. Thêm vào đó, bạn còn có thể xem mã nguồn ở các lần nộp bài của (một vài) đối thủ, nghiên cứu phương pháp của họ để biết thêm các kỹ thuật mới. Nếu bạn muốn tham gia một cuộc thi, bạn cần đăng ký một tài khoản như trong Fig. 4.10.1 (hãy làm ngay đi!).

../_images/kaggle.png

Fig. 4.10.1 Trang web Kaggle

Trên trang Dự Đoán Giá Nhà (House Prices Prediction) được mô tả ở Fig. 4.10.2, bạn có thể tìm được tập dữ liệu (dưới thanh “Data”), nộp kết quả dự đoán và xem thứ hạng của bạn, v.v. Đường dẫn:

../_images/house_pricing.png

Fig. 4.10.2 Dự đoán Giá Nhà

4.10.3. Truy cập và Đọc Bộ dữ liệu

Lưu ý rằng dữ liệu của cuộc thi được tách thành tập huấn luyện và tập kiểm tra. Mỗi tập dữ liệu bao gồm giá tiền của ngôi nhà và các thuộc tính liên quan bao gồm loại đường phố, năm xây dựng, kiểu mái nhà, tình trạng tầng hầm, v.v. Các đặc trưng được biểu diễn bởi nhiều kiểu dữ liệu. Ví dụ, năm xây dựng được biểu diễn bởi số nguyên, kiểu mái nhà là đặc trưng hạng mục rời rạc, còn các đặc trưng khác thì được biểu diễn bởi số thực dấu phẩy động (floating point number). Và đây là khi ta đối mặt với vấn đề thực tiễn: ở một vài mẫu, dữ liệu bị thiếu và được đơn thuần chú thích là ‘na’. Giá của mỗi căn nhà chỉ được cung cấp trong tập huấn luyện (sau cùng thì đây vẫn là một cuộc thi). Bạn có thể chia nhỏ tập huấn luyện để tạo tập kiểm định, tuy nhiên bạn sẽ chỉ biết được chất lượng mô hình trên tập kiểm tra chính thức khi tải kết quả dự đoán của mình lên và nhận điểm sau đó. Thanh “Data” trên cuộc thi có đường dẫn để tải bộ dữ liệu về.

Chúng ta sẽ đọc và xử lý dữ liệu với pandas, một công cụ phân tích dữ liệu hiệu quả, vì vậy hãy đảm bảo rằng bạn đã cài đặt pandas trước khi tiếp tục. Một điều may mắn là, nếu bạn đang sử dụng Jupyter, bạn có thể cài đặt pandas mà không cần thoát khỏi notebook.

# If pandas is not installed, please uncomment the following line:
# !pip install pandas

%matplotlib inline
from d2l import mxnet as d2l
from mxnet import autograd, init, np, npx
from mxnet.gluon import nn
import pandas as pd
npx.set_np()

Để thuận tiện, chúng ta sẽ tải và lưu tập dữ liệu giá nhà Kaggle từ trang web DATA_URL. Với những cuộc thi Kaggle khác, có thể bạn sẽ phải tải dữ liệu về theo cách thủ công.

# Saved in the d2l package for later use
DATA_HUB['kaggle_house_train'] = (
    DATA_URL + 'kaggle_house_pred_train.csv',
    '585e9cc93e70b39160e7921475f9bcd7d31219ce')

# Saved in the d2l package for later use
DATA_HUB['kaggle_house_test'] = (
    DATA_URL + 'kaggle_house_pred_test.csv',
    'fa19780a7b011d9b009e8bff8e99922a8ee2eb90')

Ta sử dụng Pandas để nạp lần lượt hai tệp csv chứa dữ liệu huấn luyện và kiểm tra.

train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))

Tập huấn luyện chứa \(1,460\) mẫu, \(80\) đặc trưng, và \(1\) nhãn. Tập kiểm tra chứa \(1,459\) mẫu và \(80\) đặc trưng.

print(train_data.shape)
print(test_data.shape)
(1460, 81)
(1459, 80)

Hãy cùng xem xét 4 đặc trưng đầu tiên, 2 đặc trưng cuối cùng và nhãn (giá nhà) của 4 mẫu đầu tiên:

print(train_data.iloc[0:4, [0, 1, 2, 3, -3, -2, -1]])
   Id  MSSubClass MSZoning  LotFrontage SaleType SaleCondition  SalePrice
0   1          60       RL         65.0       WD        Normal     208500
1   2          20       RL         80.0       WD        Normal     181500
2   3          60       RL         68.0       WD        Normal     223500
3   4          70       RL         60.0       WD       Abnorml     140000

Có thể thấy với mỗi mẫu, đặc trưng đầu tiên là ID. Điều này giúp mô hình xác định được từng mẫu. Mặc dù việc này khá thuận tiện, nó không mang bất kỳ thông tin nào cho mục đích dự đoán. Do đó chúng ta sẽ lược bỏ nó ra khỏi tập dữ liệu trước khi đưa vào mạng nơ-ron.

all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))

4.10.4. Tiền xử lý Dữ liệu

Như đã nói ở trên, chúng ta có rất nhiều kiểu dữ liệu. Trước khi đưa dữ liệu vào mạng học sâu, ta cần thực hiện một số phép xử lý. Hãy bắt đầu với các đặc trưng số học. Trước hết ta thay thế các giá trị còn thiếu bằng giá trị trung bình. Đây là chiến lược hợp lý nếu các đặc trưng bị thiếu một cách ngẫu nhiên. Để đưa tất cả đặc trưng số học về cùng một khoảng giá trị, ta thực hiện chuyển đổi để chúng có trung bình bằng không và phương sai đơn vị bằng cách:

(4.10.1)\[x \leftarrow \frac{x - \mu}{\sigma}.\]

Để kiểm tra xem công thức trên có chuyển đổi \(x\) thành dữ liệu với trung bình bằng không hay không, ta có thể tính \(E[(x-\mu)/\sigma] = (\mu - \mu)/\sigma = 0\). Để kiểm tra phương sai ta tính \(E[(x-\mu)^2] = \sigma^2\), như vậy biến chuyển đổi sẽ có phương sai đơn vị. Lý do của việc “chuẩn hóa” dữ liệu là để đưa tất cả các đặc trưng về cùng một độ lớn. Vì sau cùng, chúng ta không thể biết trước được đặc trưng nào là đặc trưng quan trọng.

numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
all_features[numeric_features] = all_features[numeric_features].apply(
    lambda x: (x - x.mean()) / (x.std()))
# After standardizing the data all means vanish, hence we can set missing
# values to 0
all_features[numeric_features] = all_features[numeric_features].fillna(0)

Tiếp theo chúng ta sẽ xử lý các giá trị rời rạc như biến ‘MSZoning’. Ta sẽ thay thế chúng bằng biểu diễn one-hot theo đúng cách mà ta đã chuyển đổi dữ liệu phân loại đa lớp thành vector chứa \(0\)\(1\). Ví dụ, ‘MSZoning’ bao gồm các giá trị ‘RL’ và ‘RM’, tương ứng lần lượt với vector \((1, 0)\) and \((0, 1)\). Việc này được thực hiện một cách tự động trong pandas.

# Dummy_na=True refers to a missing value being a legal eigenvalue, and
# creates an indicative feature for it
all_features = pd.get_dummies(all_features, dummy_na=True)
all_features.shape
(2919, 331)

Bạn có thể thấy sự chuyển đổi này làm tăng số lượng các đặc trưng từ 79 lên 331. Cuối cùng, thông qua thuộc tính values, ta có thể trích xuất định dạng NumPy từ khung dữ liệu Pandas và chuyển đổi nó thành biểu diễn ndarray gốc của MXNet dành cho mục đích huấn luyện.

n_train = train_data.shape[0]
train_features = np.array(all_features[:n_train].values, dtype=np.float32)
test_features = np.array(all_features[n_train:].values, dtype=np.float32)
train_labels = np.array(train_data.SalePrice.values,
                        dtype=np.float32).reshape(-1, 1)

4.10.5. Huấn luyện

Để bắt đầu, ta sẽ huấn luyện một mô hình tuyến tính với hàm mất mát bình phương. Tất nhiên là mô hình tuyến tính sẽ không thể thắng cuộc thi được, nhưng nó vẫn cho ta một phép kiểm tra sơ bộ để xem dữ liệu có chứa thông tin ý nghĩa hay không. Nếu mô hình này không thể đạt chất lượng tốt hơn việc đoán mò, khả năng cao là ta đang có lỗi trong quá trình xử lý dữ liệu. Còn nếu nó hoạt động, mô hình tuyến tính sẽ đóng vai trò như một giải pháp nền, giúp ta hình dung khoảng cách giữa một mô hình đơn giản và các mô hình tốt nhất hiện có, cũng như mức độ cải thiện mà ta mong muốn từ các mô hình “xịn” hơn.

loss = gluon.loss.L2Loss()

def get_net():
    net = nn.Sequential()
    net.add(nn.Dense(1))
    net.initialize()
    return net

Với giá nhà (hay giá cổ phiếu), ta quan tâm đến các đại lượng tương đối hơn các đại lượng tuyệt đối. Cụ thể hơn, ta thường quan tâm đến lỗi tương đối \(\frac{y - \hat{y}}{y}\) hơn lỗi tuyệt đối \(y - \hat{y}\). Ví dụ, nếu dự đoán giá một ngôi nhà ở Rural Ohio bị lệch đi 100,000 đô-la, mà giá thông thường một ngôi nhà ở đó là 125,000 đô-la, có lẽ mô hình đang làm việc rất kém. Mặt khác, nếu ta có cùng độ lệch như vậy khi dự đoán giá nhà ở Los Altos Hills, California (giá nhà trung bình ở đây tầm hơn 4 triệu đô), có thể dự đoán này lại rất chính xác.

Một cách để giải quyết vấn đề này là tính hiệu của log giá trị dự đoán và log giá trị thật sự. Thực ra đây chính là phép đo lỗi chính thức được sử dụng trong cuộc thi để đánh giá chất lượng của các lần nộp bài. Sau cùng, một giá trị \(\delta\) bằng \(\log y - \log \hat{y}\) nhỏ đồng nghĩa với việc \(e^{-\delta} \leq \frac{\hat{y}}{y} \leq e^\delta\). Điều này dẫn đến hàm mất mát sau:

(4.10.2)\[L = \sqrt{\frac{1}{n}\sum_{i=1}^n\left(\log y_i -\log \hat{y}_i\right)^2}.\]
def log_rmse(net, features, labels):
    # To further stabilize the value when the logarithm is taken, set the
    # value less than 1 as 1
    clipped_preds = np.clip(net(features), 1, float('inf'))
    return np.sqrt(2 * loss(np.log(clipped_preds), np.log(labels)).mean())

Khác với các mục trước, hàm huấn luyện ở đây sử dụng bộ tối ưu Adam (một biến thể của SGD mà chúng tôi sẽ mô tả cụ thể hơn sau này). Lợi thế chính của Adam so với SGD nguyên bản là: nó không quá nhạy cảm với tốc độ học ban đầu, mặc dù kết quả cũng không tốt hơn (đôi khi còn tệ hơn) SGD nếu tài nguyên để tối ưu siêu tham số là vô hạn. Bộ tối ưu này sẽ được mô tả cụ thể hơn trong Section 11.

def train(net, train_features, train_labels, test_features, test_labels,
          num_epochs, learning_rate, weight_decay, batch_size):
    train_ls, test_ls = [], []
    train_iter = d2l.load_array((train_features, train_labels), batch_size)
    # The Adam optimization algorithm is used here
    trainer = gluon.Trainer(net.collect_params(), 'adam', {
        'learning_rate': learning_rate, 'wd': weight_decay})
    for epoch in range(num_epochs):
        for X, y in train_iter:
            with autograd.record():
                l = loss(net(X), y)
            l.backward()
            trainer.step(batch_size)
        train_ls.append(log_rmse(net, train_features, train_labels))
        if test_labels is not None:
            test_ls.append(log_rmse(net, test_features, test_labels))
    return train_ls, test_ls

4.10.6. Kiểm định chéo gập k-lần

Nếu bạn đang đọc cuốn sách này theo đúng thứ tự thì có thể bạn sẽ nhớ ra rằng kiểm định chéo gập k-lần đã từng được giới thiệu khi ta thảo luận về cách lựa chọn mô hình (: numref: sec_model_selection). Ta sẽ ứng dụng kỹ thuật này để lựa chọn thiết kế mô hình và điều chỉnh các siêu tham số. Trước tiên ta cần một hàm trả về phần thứ \(i^\mathrm{th}\) của dữ liệu trong kiểm định chéo gập k-lần. Việc này được tiến hành bằng cách cắt chọn (slicing) phần thứ \(i^\mathrm{th}\) để làm dữ liệu kiểm định và dùng phần còn lại làm dữ liệu huấn luyện. Cần lưu ý rằng đây không phải là cách xử lý dữ liệu hiệu quả nhất và ta chắc chắn sẽ dùng một cách khôn ngoan hơn để xử lý một tập dữ liệu có kích thước lớn hơn nhiều. Nhưng sự phức tạp được thêm vào này có thể làm rối mã nguồn một cách không cần thiết, vì vậy để đơn giản hóa vấn đề ở đây ta có thể an toàn bỏ qua.

def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)
        X_part, y_part = X[idx, :], y[idx]
        if j == i:
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = np.concatenate((X_train, X_part), axis=0)
            y_train = np.concatenate((y_train, y_part), axis=0)
    return X_train, y_train, X_valid, y_valid

Trong kiểm định chéo gập k-lần, ta sẽ huấn luyện mô hình \(k\) lần và trả về trung bình lỗi huấn luyện và trung bình lỗi kiểm định.

def k_fold(k, X_train, y_train, num_epochs,
           learning_rate, weight_decay, batch_size):
    train_l_sum, valid_l_sum = 0, 0
    for i in range(k):
        data = get_k_fold_data(k, i, X_train, y_train)
        net = get_net()
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,
                                   weight_decay, batch_size)
        train_l_sum += train_ls[-1]
        valid_l_sum += valid_ls[-1]
        if i == 0:
            d2l.plot(list(range(1, num_epochs+1)), [train_ls, valid_ls],
                     xlabel='epoch', ylabel='rmse',
                     legend=['train', 'valid'], yscale='log')
        print('fold %d, train rmse: %f, valid rmse: %f' % (
            i, train_ls[-1], valid_ls[-1]))
    return train_l_sum / k, valid_l_sum / k

4.10.7. Lựa chọn Mô hình

Trong ví dụ này, chúng tôi chọn một bộ siêu tham số chưa được tinh chỉnh và để dành việc cải thiện mô hình cho bạn đọc. Để tìm ra được một bộ siêu tham số tốt có thể sẽ tốn khá nhiều thời gian tùy thuộc vào số lượng siêu tham số mà ta muốn tối ưu. Nếu được sử dụng đúng cách, phương pháp kiểm định chéo gập k-lần sẽ có tính ổn định cao khi thực hiện với nhiều thử nghiệm. Tuy nhiên, nếu thử quá nhiều các lựa chọn siêu tham số thì phương pháp này có thể thất bại vì ta có thể chỉ đơn thuần gặp may ở một cách chia tập kiểm định phù hợp với bộ siêu tham số đó.

k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64
train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr,
                          weight_decay, batch_size)
print('%d-fold validation: avg train rmse: %f, avg valid rmse: %f'
      % (k, train_l, valid_l))
fold 0, train rmse: 0.169720, valid rmse: 0.157424
fold 1, train rmse: 0.162198, valid rmse: 0.189312
fold 2, train rmse: 0.163466, valid rmse: 0.167859
fold 3, train rmse: 0.167537, valid rmse: 0.154703
fold 4, train rmse: 0.162574, valid rmse: 0.182887
5-fold validation: avg train rmse: 0.165099, avg valid rmse: 0.170437
../_images/output_kaggle-house-price_vn_b10e5d_35_1.svg

Bạn sẽ thấy rằng đôi khi lỗi huấn luyện cho một bộ siêu tham số có thể rất thấp, trong khi lỗi của kiểm định k-phần có thể cao hơn. Đây là dấu hiệu của sự quá khớp. Vì vậy khi ta giảm lỗi huấn luyện, ta cũng nên kiểm tra xem liệu lỗi kiểm định chéo gập k-lần có giảm tương ứng hay không.

4.10.8. Dự đoán và Nộp bài

Bây giờ, khi đã biết được các lựa chọn tốt cho siêu tham số, ta có thể sử dụng toàn bộ dữ liệu cho việc huấn luyện (thay vì chỉ dùng \(1-1/k\) của dữ liệu như trong quá trình kiểm định chéo). Sau đó, ta áp dụng mô hình thu được lên tập kiểm tra và lưu các dự đoán vào một tệp CSV nhằm đơn giản hóa quá trình tải kết quả lên Kaggle.

def train_and_pred(train_features, test_feature, train_labels, test_data,
                   num_epochs, lr, weight_decay, batch_size):
    net = get_net()
    train_ls, _ = train(net, train_features, train_labels, None, None,
                        num_epochs, lr, weight_decay, batch_size)
    d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',
             ylabel='rmse', yscale='log')
    print('train rmse %f' % train_ls[-1])
    # Apply the network to the test set
    preds = net(test_features).asnumpy()
    # Reformat it for export to Kaggle
    test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])
    submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)
    submission.to_csv('submission.csv', index=False)

Ta nên kiểm tra xem liệu các dự đoán trên tập kiểm tra có tương đồng với các dự đoán trong quá trình kiểm định chéo k-phần hay không. Nếu đúng là như vậy thì đã đến lúc tải các dự đoán này lên Kaggle. Đoạn mã nguồn sau sẽ tạo một tệp có tên submission.csv (CSV là một trong những định dạng tệp được chấp nhận bởi Kaggle):

train_and_pred(train_features, test_features, train_labels, test_data,
               num_epochs, lr, weight_decay, batch_size)
train rmse 0.162490
../_images/output_kaggle-house-price_vn_b10e5d_39_1.svg

Tiếp theo, như được mô tả trong hình Fig. 4.10.3, ta có thể nộp các dự đoán lên Kaggle và so sánh chúng với giá nhà thực tế (các nhãn) trên tập kiểm tra. Các bước tiến hành khá là đơn giản:

  • Đăng nhập vào trang web Kaggle và tìm đến trang của cuộc thi “House Price Prediction”.
  • Nhấn vào nút “Submit Predictions” hoặc “Late Submission” (nút này nằm ở phía bên phải tại thời điểm viết sách).
  • Nhấn vào nút “Upload Submission File” trong khung có viền nét đứt và chọn tệp dự đoán bạn muốn tải lên.
  • Nhấn vào nút “Make Submission” ở cuối trang để xem kết quả.
../_images/kaggle_submit2.png

Fig. 4.10.3 Tải dữ liệu lên Kaggle

4.10.9. Tóm tắt

  • Dữ liệu trong thực tế thường chứa nhiều kiểu dữ liệu khác nhau và cần phải được tiền xử lý.
  • Chuyển đổi dữ liệu có giá trị thực để có trung bình bằng không và phương sai đơn vị là một phương án mặc định tốt. Tương tự với việc thay thế các giá trị bị thiếu bằng giá trị trung bình.
  • Chuyển đổi các biến hạng mục thành các biến chỉ định cho phép chúng ta xử lý chúng như các vector.
  • Ta có thể sử dụng kiểm định chéo gập k-phần để chọn ra mô hình và điều chỉnh siêu tham số.
  • Hàm Logarit có hữu ích đối với mất mát tương đối.

4.10.10. Bài tập

  1. Nộp kết quả dự đoán của bạn từ bài hướng dẫn này cho Kaggle. Các dự đoán của bạn tốt đến đâu?
  2. Bạn có thể cải thiện mô hình bằng cách giảm thiểu trực tiếp log giá nhà không? Điều gì sẽ xảy ra nếu bạn dự đoán log giá nhà thay vì giá thực?
  3. Liệu việc thay thế các giá trị bị thiếu bằng trung bình của chúng luôn luôn tốt? Gợi ý: bạn có thể dựng lên một tình huống khi mà các giá trị không bị thiếu một cách ngẫu nhiên không?
  4. Tìm cách biểu diễn tốt hơn để đối phó với các giá trị bị thiếu. Gợi ý: điều gì sẽ xảy ra nếu bạn thêm vào một biến chỉ định?
  5. Cải thiện điểm trên Kaggle bằng cách điều chỉnh các siêu tham số thông qua kiểm định chéo gập k-lần.
  6. Cải thiện điểm bằng cách cải thiện mô hình (các tầng, điều chuẩn, dropout).
  7. Điều gì sẽ xảy ra nếu ta không chuẩn hóa đặc trưng số liên tục như ta đã làm trong phần này?

4.10.11. Thảo luận

4.10.12. Những người thực hiện

Bản dịch trong trang này được thực hiện bởi:

  • Đoàn Võ Duy Thanh
  • Nguyễn Lê Quang Nhật
  • Phạm Minh Đức
  • Lê Khắc Hồng Phúc
  • Phạm Hồng Vinh
  • Nguyễn Duy Du
  • Trần Yến Thy
  • Vũ Hữu Tiệp