Dari pengumpulan dan persiapan data hingga pelatihan dan evaluasi model — termasuk kode sumber.

Pembelajaran mendalam adalah suatu hal yang penting saat ini. Bahkan, ini merupakan persyaratan untuk sebagian besar pekerjaan ilmu data, bahkan pekerjaan tingkat pemula. Tidak ada kuliah pengantar yang lebih baik daripada regresi. Anda sudah mengetahui konsep statistik dasar dan pembelajaran mesin, dan sekarang saatnya menggabungkan jaringan saraf.

Artikel ini akan menunjukkan caranya. Pada akhirnya, Anda akan memiliki model yang berfungsi penuh untuk memprediksi harga rumah yang dapat Anda lampirkan ke portofolio Anda — setelah beberapa modifikasi, lebih disukai.

Tidak ingin membaca? Tonton video saya sebagai gantinya:

Artikel hari ini mencakup topik-topik berikut:

· Dataset used
· Dataset exploration and preparationDeleting unnecessary columnsFeature engineeringTarget variable visualizationData preparation for ML
· Training a regression model with TensorFlowLoss trackingBuilding a modelMaking predictionsModel evaluation

Anda dapat mengunduh kode sumber di GitHub.

Kumpulan data yang digunakan

Mari kita buat semuanya tetap sederhana hari ini dan tetap menggunakan “Kumpulan data harga rumah” yang terkenal:

Ia memiliki banyak fitur yang pada awalnya tidak dapat digunakan dengan model jaringan saraf, jadi Anda harus meluangkan waktu untuk mengatasinya. Unduh kumpulan data, ekstrak file ZIP, dan letakkan kumpulan data CSV di tempat yang aman.

Kemudian aktifkan lingkungan virtual yang telah menginstal TensorFlow 2+ dan luncurkan JupyterLab. Anda bebas menggunakan IDE lain, tetapi semua tangkapan layar di bawah berasal dari Jupyter.

Eksplorasi dan persiapan kumpulan data

Langkah pertama adalah mengimpor Numpy dan Pandas, lalu mengimpor dataset. Cuplikan berikut melakukan hal itu dan juga mencetak beberapa baris acak:

import numpy as np
import pandas as pd

df = pd.read_csv('data/data.csv')
df.sample(5)

Berikut tampilan kumpulan datanya:

Anda pasti tidak dapat meneruskannya ke jaringan saraf dalam format ini.

Menghapus kolom yang tidak diperlukan

Karena kami ingin menghindari menghabiskan terlalu banyak waktu untuk menyiapkan data, sebaiknya hilangkan sebagian besar fitur non-numerik. Pertahankan hanya kolom city, karena cukup sederhana untuk dikodekan:

to_drop = ['date', 'street', 'statezip', 'country']
df = df.drop(to_drop, axis=1)

df.head()

Begini tampilannya sekarang:

Anda pasti dapat menyimpan semua kolom dan melakukan beberapa rekayasa fitur dengannya. Hal ini kemungkinan akan meningkatkan performa model. Namun ini pun sudah cukup untuk memenuhi kebutuhan Anda saat ini.

Rekayasa fitur

Sekarang Anda akan meluangkan waktu untuk mengubah kumpulan data. Kolom yr_renovated terkadang bernilai 0. Saya berasumsi itu karena rumahnya tidak direnovasi. Anda akan membuat beberapa fitur — usia rumah, apakah rumah tersebut direnovasi atau tidak, apakah direnovasi dalam 10 tahun terakhir, dan apakah direnovasi dalam 30 tahun terakhir.

Anda dapat menggunakan pemahaman daftar untuk setiap fitur yang disebutkan. Begini caranya:

# How old is the house?
df['house_age'] = [2021 - yr_built for yr_built in df['yr_built']]

# Was the house renovated and was the renovation recent?
df['was_renovated'] = [1 if yr_renovated != 0 else 0 
    for yr_renovated in df['yr_renovated']]
df['was_renovated
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['figure.figsize'] = (16, 6)
rcParams['axes.spines.top'] = False
rcParams['axes.spines.right'] = False

plt.hist(df['price'], bins=100);
yrs'] = [1 if (2021 - yr_renovated) <= 10 else 0 for yr_renovated in df['yr_renovated']] df['was_renovatedravel()yrs'] = [1 if 10 < (2021 - yr_renovated) <= 30 else 0 for yr_renovated in df['yr_renovated']] # Drop original columns df = df.drop(['yr_built', 'yr_renovated'], axis=1) df.head()

Berikut tampilan kumpulan datanya sekarang:

Mari kita tangani kolom city selanjutnya. Banyak kota yang hanya memiliki beberapa rumah yang terdaftar, sehingga Anda dapat mendeklarasikan fungsi yang akan menghilangkan semua nilai kota yang tidak sering muncul. Itulah yang akan dilakukan fungsi remap_location() — jika jumlah rumah di kota tersebut kurang dari 50, maka akan diganti dengan yang lain. Ini hanyalah cara untuk mengurangi jumlah pilihan:

def remap_location(data: pd.DataFrame, 
                   location: str, 
                   threshold: int = 50) -> str:
    if len(data[data['city'] == location]) < threshold:
        return 'Rare'
    return location

Mari kita uji fungsinya — kota Seattle memiliki banyak rumah yang terdaftar, sedangkan Fall City hanya memiliki 11:

Mari terapkan fungsi ini ke semua kota dan cetak sampel 10 baris:

df['city'] = df['city'].apply(
    lambda x: remap_location(data=df, location=x)
)
df.sample(10)

Semuanya tampak sebagaimana mestinya, jadi mari kita lanjutkan.

Visualisasi variabel target

Kapan pun Anda berurusan dengan harga, kecil kemungkinan variabel target akan terdistribusi secara normal. Dan kumpulan data perumahan ini tidak terkecuali. Mari kita verifikasi dengan mengimpor Matplotlib dan memvisualisasikan distribusinya dengan Histogram:

import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['figure.figsize'] = (16, 6)
rcParams['axes.spines.top'] = False
rcParams['axes.spines.right'] = False

plt.hist(df['price'], bins=100);

Berikut tampilannya:

Pencilan pasti ada, jadi mari kita tangani selanjutnya. Hal yang cukup umum dilakukan adalah menghitung Z-score. Mereka memberi tahu Anda berapa banyak standar deviasi suatu nilai yang terletak dari mean. Dalam kasus distribusi normal, segala sesuatu yang berada di bawah atau di atas 3 standar deviasi diklasifikasikan sebagai outlier. Distribusi harga memang tidak normal, tapi mari kita tetap melakukan uji Z untuk menghilangkan rumah-rumah di paling kanan.

Anda dapat menghitung Z-score dengan Scipy. Anda akan menetapkannya sebagai kolom kumpulan data baru — price_z, lalu hanya menyimpan baris yang nilai absolutnya kurang dari atau sama dengan tiga.

Ada juga sekitar 50 rumah yang terdaftar seharga $0, jadi Anda juga akan menghapusnya:

from scipy import stats

# Calculate Z-values
df['price_z'] = np.abs(stats.zscore(df['price']))

# Filter out outliers
df = df[df['price_z'] <= 3]

# Remove houses listed for $0
df = df[df['price'] != 0]

# Drop the column
df = df.drop('price_z', axis=1)

# Draw a histogram
plt.hist(df['price'], bins=100);

Berikut tampilan distribusinya sekarang:

Masih ada sedikit penyimpangan, namun mari kita nyatakan cukup baik.

Sebagai langkah terakhir, mari ubah data ke dalam format yang siap untuk pembelajaran mesin.

Persiapan data untuk ML

Jaringan saraf hanya suka melihat data numerik pada skala yang sama. Kumpulan data kami tidak, dan kami juga memiliki beberapa data non-numerik. Di sinilah penskalaan data dan enkode one-hot berperan.

Anda sekarang dapat mengubah setiap fitur satu per satu, namun ada cara yang lebih baik. Anda dapat menggunakan fungsi make_column_transformer() dari Scikit-Learn untuk menerapkan penskalaan dan pengkodean sekaligus.

Anda dapat mengabaikan fitur seperti waterfront, was_renovated, was_renovated_10_yrs, dan was_renovatedravel()yrs, karena fitur tersebut sudah dalam format yang Anda perlukan:

from sklearn.compose import make_column_transformer
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder

transformer = make_column_transformer(
    (MinMaxScaler(), 
        ['sqft_living', 'sqft_lot','sqft_above', 
         'sqft_basement', 'house_age']),
    (OneHotEncoder(handle_unknown='ignore'), 
        ['bedrooms', 'bathrooms', 'floors', 
         'view', 'condition'])
)

Selanjutnya, pisahkan fitur dari variabel target, dan bagi kumpulan data menjadi bagian pelatihan dan pengujian. Kumpulan kereta akan mencakup 80% data, dan kami akan menggunakan sisanya untuk pengujian:

from sklearn.model_selection import train_test_split

X = df.drop('price', axis=1)
y = df['price']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

Dan terakhir, Anda dapat menerapkan transformasi yang dideklarasikan satu menit yang lalu. Anda akan menyesuaikan dan mengubah fitur pelatihan, dan hanya menerapkan transformasi tersebut ke set pengujian:

# Fit
transformer.fit(X_train)

# Apply the transformation
X_train = transformer.transform(X_train)
X_test = transformer.transform(X_test)

Anda tidak akan dapat memeriksa X_train dan X_test secara langsung, karena keduanya sekarang disimpan sebagai matriks renggang:

TensorFlow tidak akan bisa membaca format tersebut, jadi Anda harus mengonversinya menjadi array Numpy multidimensi. Anda dapat menggunakan fungsi toarray(). Berikut ini contohnya:

X_train.toarray()

Ubah kedua set fitur menjadi array Numpy, dan Anda siap melakukannya:

X_train = X_train.toarray()
X_test = X_test.toarray()

Terakhir, mari kita latih modelnya.

Melatih model regresi dengan TensorFlow

Anda sekarang akan membuat model sekuensial yang terbuat dari lapisan yang terhubung sepenuhnya. Ada banyak hal impor yang harus dilakukan, jadi mari kita selesaikan hal tersebut:

import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import backend as K

Pelacakan kerugian

Di sini Anda berurusan dengan harga rumah, jadi kerugiannya bisa sangat besar jika Anda melacaknya melalui, katakanlah, kesalahan kuadrat rata-rata. Metrik tersebut juga tidak terlalu berguna bagi Anda, karena pada dasarnya metrik tersebut memberi tahu Anda seberapa salah model Anda dalam satuan kuadrat.

Anda dapat menghitung akar kuadrat UMK untuk kembali ke unit aslinya. Metrik tersebut tidak didukung secara default, namun kami dapat mendeklarasikannya secara manual. Ingatlah bahwa Anda harus menggunakan fungsi dari backend Keras untuk membuatnya berfungsi:

def rmse(y_true, y_pred):
    return K.sqrt(K.mean(K.square(y_pred - y_true)))

Membangun model

Dan sekarang Anda akhirnya dapat mendeklarasikan sebuah model. Ini akan menjadi sederhana, hanya memiliki tiga lapisan tersembunyi sebanyak 256, 256, dan 128 unit. Jangan ragu untuk bereksperimen dengan hal ini, karena tidak ada cara yang benar atau salah dalam menyiapkan jaringan saraf. Lapisan ini kemudian diikuti oleh lapisan keluaran dari satu node, karena Anda memperkirakan nilai numerik.

Anda kemudian akan mengkompilasi model menggunakan RMSE sebagai cara untuk melacak kerugian dan sebagai metrik evaluasi, dan Anda akan mengoptimalkan model menggunakan pengoptimal Adam.

Terakhir, Anda akan melatih model pada data pelatihan selama 100 epoch:

tf.random.set_seed(42)

model = Sequential([
    Dense(256, activation='relu'),
    Dense(256, activation='relu'),
    Dense(128, activation='relu'),
    Dense(1)
])

model.compile(
    loss=rmse,
    optimizer=Adam(),
    metrics=[rmse]
)

model.fit(X_train, y_train, epochs=100)

Pelatihan akan selesai dalam satu menit atau lebih, tergantung pada perangkat keras di belakangnya:

Nilai RMSE akhir pada set pelatihan tepat di atas 192.000, yang berarti bahwa untuk rumah rata-rata, model tersebut salah dalam memperkirakan harga sebesar $192.000.

Membuat prediksi

Anda dapat membuat prediksi pada set pengujian:

predictions = model.predict(X_test)
predictions[:5]

Berikut tampilan lima prediksi pertama:

Anda harus mengonversinya menjadi array 1 dimensi jika ingin menghitung metrik apa pun. Anda dapat menggunakan fungsi ravel() dari Numpy untuk melakukannya:

predictions = np.ravel(predictions)
predictions[:5]

Berikut hasilnya:

Evaluasi model

Dan sekarang mari kita evaluasi prediksi pada set pengujian dengan menggunakan RMSE:

rmse(y_test, predictions).numpy()

Anda akan mendapatkan 191000 sebagai nilai kesalahan, yang menunjukkan model belum melakukan overfitting pada data pelatihan. Anda mungkin akan mendapatkan hasil yang lebih baik dengan pelatihan model yang lebih kompleks untuk jangka waktu yang lebih lama. Itu adalah sesuatu yang dapat Anda coba sendiri.

Kata-kata perpisahan

Dan itu berhasil — Anda sudah melatih model jaringan saraf sederhana sekarang, dan Anda tahu cara membuat prediksi pada data baru. Namun, masih banyak yang bisa Anda tingkatkan.

Misalnya, Anda dapat menghabiskan lebih banyak waktu untuk menyiapkan data. Kami menghapus fitur tanggal-waktu, informasi jalan, kode pos, dan sebagainya, yang dapat bermanfaat bagi performa model. Masalahnya adalah — persiapannya akan memakan banyak waktu, dan saya ingin artikel ini dibuat singkat.

Anda juga dapat menambahkan lapisan tambahan ke jaringan, menambah jumlah neuron, memilih fungsi aktivasi yang berbeda, memilih pengoptimal yang berbeda, menambahkan lapisan putus sekolah, dan banyak lagi. Kemungkinannya hampir tidak terbatas, jadi semuanya bergantung pada eksperimen.

Artikel berikut akan membahas cara membuat model klasifikasi menggunakan TensorFlow, jadi pantau terus jika Anda ingin mempelajari lebih lanjut.

Terima kasih sudah membaca.

Suka dengan artikelnya? Menjadi Medium member untuk terus belajar tanpa batas. Saya akan menerima sebagian dari biaya keanggotaan Anda jika Anda menggunakan tautan berikut, tanpa biaya tambahan untuk Anda.



Tetap terhubung