TÌM HIỂU VỀ STOCHASTIC GRADIENT DESCENT

TÌM HIỂU VỀ STOCHASTIC GRADIENT DESCENT

Uniduc JSC - 2020-04-01 00:00:55 | 3000 lượt xem

Mục lục

Stochastic Gradient Descent là gì?

Trong phần trước, chúng ta đã thảo luận về Gradient Descent, thuật toán tối ưu hóa bậc nhất có thể được sử dụng để học một tập các trọng số phân loại cho việc Parameterized Learning. Tuy nhiên, Vanilla Gradient Descent thực hiện gradient descent có thể bị chậm khi chạy trên các bộ dữ liệu lớn - trên thực tế, nó thậm chí có thể được coi là lãng phí tính toán.


Thay vào đó, chúng ta nên áp dụng Stochastic Gradient Descent (SGD), một sửa đổi đơn giản cho thuật toán gradient descent tính toán độ dốc và cập nhật ma trận trọng số W trên các booj dữ liệu đào tạo nhỏ, thay vì toàn bộ tập huấn luyện. Trong khi sửa đổi này dẫn đến các bản cập nhật khác nhiều nhiễu hơn, nó cũng cho phép chúng ta thực hiện nhiều bước hơn học theo gradient (mỗi bước một bước mỗi đợt so với một bước trên mỗi epoch), cuối cùng dẫn đến sự hội tụ nhanh hơn và không có ảnh hưởng tiêu cực đến mất mát và phân loại chính xác.
SGD được cho là thuật toán quan trọng nhất khi đào tạo mạng lưới thần kinh sâu. Mặc dù hóa thân ban đầu của SGD đã được giới thiệu hơn 57 năm trước, nó vẫn là công cụ cho phép chúng ta đào tạo các mạng lớn để tìm hiểu các mẫu từ các điểm dữ liệu.

Mini-batch SGD là gi?

Xem xét thuật toán vanilla GD, rõ ràng là phương thức này sẽ chạy rất chậm trên các tập dữ liệu lớn. Lý do cho sự chậm chạp này là vì mỗi lần lặp lại của
gradient, chúng ta cần tính toán dự đoán cho từng điểm đào tạo trong dữ liệu đào tạo của chúng ta trước khi chúng ta được phép cập nhật ma trận trọng số của chúng ta. Đối với các bộ dữ liệu hình ảnh như ImageNet là chúng ta có hơn 1,2 triệu hình ảnh đào tạo, việc tính toán này có thể mất nhiều thời gian.
Nó cũng chỉ ra rằng dự đoán điện toán cho mọi điểm đào tạo trước khi thực hiện một bước ma trận trọng số của chúng ta là lãng phí tính toán và không giúp được gì cho mô hình của chúng ta.


Thay vào đó, những gì chúng ta nên làm là hàng loạt cập nhật của chúng ta. Chúng ta có thể cập nhật mã giả để chuyển đổi Vanilla GD để trở thành SGD bằng cách thêm một lệnh gọi hàm:

while True:
    batch = next_training_batch(data, 256)
    Wgradient = evaluate_gradient(loss, batch, W)
    W += -alpha * Wgradient

Sự khác biệt duy nhất giữa gốc Vanilla GD và SGD là sự bổ sung của hàm next_training_batch. Thay vì tính toán độ dốc của chúng tôi trên toàn bộ tập dữ liệu, chúng ta thay vào đó lấy mẫu dữ liệu của chúng ta, thu được một batch. Chúng tôi đánh giá gradient trên batch và cập nhật trọng số của chúng ta
ma trận W. Từ góc độ thực thi, chúng ta cũng cố gắng chọn ngẫu nhiên các mẫu đào tạo của chúng ta trước khi áp dụng SGD vì thuật toán rất nhạy cảm với các batch.


Sau khi xem mã giả cho SGD, bạn sẽ ngay lập tức nhận thấy sự giới thiệu mới tham số: kích thước batch. Trong một triển khai SGD thuần túy của SGD, kích thước batch nhỏ của bạn sẽ là 1, ngụ ý rằng chúng ta sẽ lấy mẫu ngẫu nhiên một điểm dữ liệu từ tập huấn luyện, tính toán gradient, và cập nhật các thông số của chúng ta. Tuy nhiên, chúng ta thường sử dụng các batch nhỏ có kích thước> 1. Kích thước batch điển hình bao gồm 32, 64, 128 và 256.


Vì vậy, tại sao phải sử dụng kích thước batch> 1?

  1.  Để bắt đầu, kích thước batch> 1 giúp giảm phương sai trong cập nhật tham số, dẫn đến sự hội tụ ổn định hơn.
  2. Thứ hai, mũ hai thường được sử dụng cho kích thước batch vì chúng cho phép các thư viện tối ưu hóa đại số tuyến tính bên trong để có hiệu quả hơn.

Nói chung, kích thước lô nhỏ không phải là siêu tham số, bạn nên lo lắng quá nhiều vềchúng. Nếu bạn sử dụng GPU để huấn luyện mạng thần kinh, bạn sẽ xác định có bao nhiêu ví dụ đào tạo sẽ phù hợp với GPU của bạn và sau đó sử dụng sức mạnh gần nhất của hai như kích thước batch sao cho batch đó sẽ phù hợp với GPU. Để đào tạo CPU, bạn thường sử dụng một trong các kích thước batch được liệt kê ở trên để đảm bảo bạn có được những lợi ích của thư viện tối ưu hóa đại số tuyến tính

Mini-batch SGD trong Python

Thực thi file sgd.py

from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
import argparse

def sigmoid_activation(x):
	# compute the sigmoid activation value for a given input
	return 1.0 / (1 + np.exp(-x))

def sigmoid_deriv(x):
	# compute the derivative of the sigmoid function ASSUMING
	# that the input `x` has already been passed through the sigmoid
	# activation function
	return x * (1 - x)

def predict(X, W):
	# take the dot product between our features and weight matrix
	preds = sigmoid_activation(X.dot(W))

	# apply a step function to threshold the outputs to binary
	# class labels
	preds[preds <= 0.5] = 0
	preds[preds > 0] = 1

	# return the predictions
	return preds

def next_batch(X, y, batch_size):
	for i in range(0, len(X), batch_size):
		yield X[i:i+batch_size], y[i:i+batch_size]	

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-e", "--epochs", type=float, default=100,
	help="# of epochs")
ap.add_argument("-a", "--alpha", type=float, default=0.01,
	help="learning rate")
ap.add_argument("-b", "--batch-size", type=int, default=32,
	help="size of SGD mini-batches")
args = vars(ap.parse_args())

# generate a 2-class classification problem with 1,000 data points,
# where each data point is a 2D feature vector
(X, y) = make_blobs(n_samples=1000, n_features=2, centers=2,
	cluster_std=1.5, random_state=1)
y = y.reshape((y.shape[0], 1))

# insert a column of 1's as the last entry in the feature
# matrix -- this little trick allows us to treat the bias
# as a trainable parameter within the weight matrix
X = np.c_[X, np.ones((X.shape[0]))]

# partition the data into training and testing splits using 50% of
# the data for training and the remaining 50% for testing
(trainX, testX, trainY, testY) = train_test_split(X, y,
	test_size=0.5, random_state=42)

# initialize our weight matrix and list of losses
print("[INFO] training...")
W = np.random.randn(X.shape[1], 1)
losses = []

# loop over the desired number of epochs
for epoch in np.arange(0, args["epochs"]):
	epoch_loss = []

	for batchX, batchY in next_batch(trainX, trainY, args['batch_size']):
		preds = sigmoid_activation(batchX.dot(W))

		error = preds - batchY

		epoch_loss.append(np.sum(error ** 2))

		d = error * sigmoid_deriv(preds)

		gradient = batchX.T.dot(d)

		W -= args['alpha'] * gradient

	loss = np.mean(epoch_loss)
	losses.append(loss)

	# check to see if an update should be displayed
	if epoch == 0 or (epoch + 1) % 5 == 0:
		print("[INFO] epoch={}, loss={:.7f}".format(int(epoch + 1),
			loss))

# evaluate our model
print("[INFO] evaluating...")
preds = predict(testX, W)
print(classification_report(testY, preds))

# plot the (testing) classification data
plt.style.use("ggplot")
plt.figure()
plt.title("Data")
plt.scatter(testX[:, 0], testX[:, 1], marker="o", c=testY[:, 0], s=30)

# construct a figure that plots the loss over time
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, args["epochs"]), losses)
plt.title("Training Loss")
plt.xlabel("Epoch #")
plt.ylabel("Loss")
plt.show()

Kết quả của code

[INFO] epoch=1, loss=0.1317637
[INFO] epoch=5, loss=0.0162487
[INFO] epoch=10, loss=0.0112798
[INFO] epoch=15, loss=0.0100234
[INFO] epoch=20, loss=0.0094581
[INFO] epoch=25, loss=0.0091053
[INFO] epoch=30, loss=0.0088366
[INFO] epoch=35, loss=0.0086082
[INFO] epoch=40, loss=0.0084031
[INFO] epoch=45, loss=0.0082138
[INFO] epoch=50, loss=0.0080364
[INFO] epoch=55, loss=0.0078690
[INFO] epoch=60, loss=0.0077102
[INFO] epoch=65, loss=0.0075593
[INFO] epoch=70, loss=0.0074153
[INFO] epoch=75, loss=0.0072779
[INFO] epoch=80, loss=0.0071465
[INFO] epoch=85, loss=0.0070207
[INFO] epoch=90, loss=0.0069001
[INFO] epoch=95, loss=0.0067843
[INFO] epoch=100, loss=0.0066731
[INFO] evaluating...
  Precision Recall f1-score Support
0 1.00 1.00 1.00 250
1 1.00 1.00 1.00 250
avg / total 1.00 1.00 1.00 500

Kết luận

Điều tra các giá trị loss thực tế ở epoch thứ 100, bạn sẽ nhận thấy rằng loss thu được bởi SGD có độ lớn bậc hai  thấp hơn Vanilla GD (0: 006 so với 0: 447, tương ứng). Sự khác biệt này là do nhiều cập nhật trọng số trên mỗi epoch, đưa ra mô hình của chúng ta nhiều cơ hội hơn để học hỏi từ các bản cập nhật được thực hiện cho ma trận trọng số. Hiệu ứng này thậm chí còn nhiều hơn trên các bộ dữ liệu lớn, chẳng hạn như ImageNet, nơi chúng ta có hàng triệu ví dụ đào tạo và cập nhật nhỏ, gia tăng trong các tham số của chúng ta có thể dẫn đến giải pháp có loss thấp (nhưng không nhất thiết là tối ưu).

Chúc bạn thành đạt trong công việc và hạnh phúc trong cuộc sống !

Hotline / Zalo: 0903 666 014

Website: https://uniduc.com/vi

-------------////--------------------------------------------////------------

HUMANOID ROBOT CỦA CÔNG TY UNIDUC SẢN XUẤT PHÁT TRIỂN.

Đăng kí nhận tin mới



Đánh giá bài viết

0%

0 Tổng người đánh giá
5
0%
4
0%
3
0%
2
0%
1
0%
THÔNG TIN LIÊN HỆ

Công ty Cổ phần Uniduc

Địa Chỉ: 22 Đường Số 54, Phường Thảo Điền, Quận 2

Hotline: 086 567 7939 (Phòng Kinh Doanh / HTKT)

Email: [email protected]

Website: https://uniduc.com/vi

 

 
TỔNG QUAN

Công ty Cổ Phần Uniduc chuyên cung cấp các loại robot phục vụ, Agv Robot, hệ thống tự động. Với kinh nghiệm nghiên cứu lâu năm và đội ngũ kỹ sư năng động sáng tạo. Hi vọng Uniduc là điếm đến công nghệ là nơi khách hàng luôn gửi trọn niềm tin. Chúng tôi sẽ luôn luôn phấn đấu cung cấp cho bạn giải pháp, máy móc, dịch vụ tốt nhất.

TIN MỚI
ĐĂNG KÝ NHẬN TIN

Nhận bản tin thường xuyên để cập nhật giá bán và các chương trình khuyến mãi.


©2018 - 2022 Copyright Uniduc., Jsc. Sitemap