Giới thiệu về Deep Learning và Neuron
Deep Learning là một nhánh của Machine Learning, mô phỏng cách hoạt động của bộ não con người thông qua các mạng neural nhân tạo. Đơn vị cơ bản của mạng neural là neuron, một mô hình toán học đơn giản hóa của tế bào thần kinh sinh học. Mỗi neuron nhận đầu vào, nhân với trọng số, cộng thêm bias và chạy qua một hàm kích hoạt để tạo ra đầu ra.
Công thức cơ bản của một neuron:
y = activation_function(Σ(weight_i * input_i) + bias)
Ví dụ, với hàm kích hoạt sigmoid, một neuron có thể được biểu diễn như sau:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
# Giả sử đầu vào x = [1, 2, 3], trọng số w = [0.7, 0.6, 1.4], bias = 1
x = [1, 2, 3]
w = [0.7, 0.6, 1.4]
bias = 1
z = sum(x_i * w_i for x_i, w_i in zip(x, w)) + bias
output = sigmoid(z)
print(output) # Kết quả sẽ là 0.999...
Ví dụ thực tế: Dự đoán mua bảo hiểm nhân thọ
Chúng ta sẽ sử dụng hồi quy logistic (một dạng đơn giản của neural network) để dự đoán một người có mua bảo hiểm nhân thọ dựa trên độ tuổi của họ không.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
df = pd.read_csv("insurance_data.csv")
X_train, X_test, y_train, y_test = train_test_split(df[['age']], df['bought_insurance'], test_size=0.2)
model = LogisticRegression()
model.fit(X_train, y_train)
print(model.score(X_test, y_test))
# Lấy hệ số (coef_) và độ dốc (intercept_)
# Hàm sigmoid: y = 1 / (1 + exp(-(m*x + b)))
print("Hệ số m:", model.coef_)
print("Độ dốc b:", model.intercept_)
Hệ số m (coef_) và độ dốc b (intercept_) trong phương trình đường thẳng y = m*x + b chính là trọng số và bias của neuron.
Xây dựng Neural Network từ đầu
Ta sẽ tự xây dựng một mạng neural đơn giản mà không cần thư viện Deep Learning.
import numpy as np
import matplotlib.pyplot as plt
# 1. Hàm kích hoạt sigmoid và đạo hàm của nó
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
return sigmoid(x) * (1 - sigmoid(x))
# 2. Dữ liệu huấn luyện (bài toán XOR)
X = np.array([[0, 0], [0, 1], [1, 1], [1, 0]])
y = np.array([[0], [1], [1], [0]])
# 3. Khởi tạo trọng số và bias ngẫu nhiên
np.random.seed(10)
weights = np.random.rand(2, 1)
bias = np.random.rand(1)
learning_rate = 0.5
epochs = 2000
# 4. Huấn luyện
loss_history = []
for epoch in range(epochs):
# Forward propagation
z = np.dot(X, weights) + bias
output = sigmoid(z)
# Tính loss
loss = np.mean((output - y) ** 2)
loss_history.append(loss)
# Backpropagation
error = output - y
d_sigmoid = sigmoid_derivative(output)
derivative = error * d_sigmoid
final_derivative = np.dot(X.T, derivative)
# Cập nhật trọng số và bias
weights -= learning_rate * final_derivative
for d in derivative:
bias -= learning_rate * d
# Vẽ biểu đồ loss
plt.plot(loss_history)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()
# 5. Dự đoán
def predict(inputs):
z = np.dot(inputs, weights) + bias
return sigmoid(z) >= 0.5
print(predict(np.array([1, 0]))) # Kết quả: False
Sử dụng Keras và TensorFlow
Thay vì tự xây dựng, ta có thể sử dụng Keras (tích hợp trong TensorFlow) để xây dựng mạng neural nhanh chóng.
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
# Dữ liệu (Pima Indians Diabetes)
dataset = np.loadtxt('pima-indians-diabetes.data', delimiter=',')
X = dataset[:, 0:8]
y = dataset[:, 8]
# Xây dựng mô hình
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Huấn luyện
model.fit(X, y, epochs=200, batch_size=10)
# Đánh giá
_, accuracy = model.evaluate(X, y)
print(f'Độ chính xác: {accuracy * 100:.2f}%')
Tại sao ReLU lại tốt hơn Sigmoid?
Hàm kích hoạt ReLU (Rectified Linear Unit) thường được ưa chuộng hơn Sigmoid vì lý do Vanishing Gradient (độ dốc biến mất). Với Sigmoid, khi giá trị đầu vào rất lớn hoặc rất nhỏ, đạo hàm của nó gần bằng 0, khiến cho việc cập nhật trọng số trong quá trình backpropagation trở nên rất chậm, đặc biệt ở các lớp sâu.
ReLU khắc phục điều này vì đạo hàm của nó là 1 đối với đầu vào dương và 0 đối với đầu vào âm, giúp gradient không bị "biến mất".
So sánh các hàm kích hoạt
Khi xây dựng mô hình, việc lựa chọn hàm kích hoạt ảnh hưởng lớn đến hiệu suất. Dưới đây là ví dụ so sánh Tanh, ReLU và Sigmoid trên cùng một bài toán phân loại (make_circles).
from sklearn.datasets import make_circles
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import SGD
from keras.initializers import RandomUniform
import matplotlib.pyplot as plt
# Tạo dữ liệu
X, y = make_circles(n_samples=1000, noise=0.1, random_state=1)
scaler = MinMaxScaler(feature_range=(-1, 1))
X = scaler.fit_transform(X)
# Chia train/test
n_train = 500
trainX, testX = X[:n_train, :], X[n_train:, :]
trainy, testy = y[:n_train], y[n_train:]
def create_model(activation):
model = Sequential()
init = RandomUniform(minval=0, maxval=1)
model.add(Dense(5, input_dim=2, activation=activation, kernel_initializer=init))
model.add(Dense(1, activation='sigmoid', kernel_initializer=init))
return model
# Huấn luyện với các hàm kích hoạt khác nhau
for activation in ['tanh', 'relu', 'sigmoid']:
model = create_model(activation)
opt = SGD(lr=0.01, momentum=0.9)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=500, verbose=0)
# Vẽ biểu đồ
plt.plot(history.history['accuracy'], label=f'{activation}_train')
plt.plot(history.history['val_accuracy'], label=f'{activation}_test')
plt.legend()
plt.show()
Kết quả cho thấy Tanh và ReLU thường cho hiệu suất tốt hơn Sigmoid trong các mạng có nhiều lớp.