Cảm ơn bạn rất nhiều amip vì cái nhìn sâu sắc về trọng lượng hàng. Tôi biết rằng đây không phải là stackoverflow, nhưng tôi đã gặp một số khó khăn khi tìm cách triển khai PCA có trọng số hàng với lời giải thích và, vì đây là một trong những kết quả đầu tiên khi googling cho PCA có trọng số, tôi nghĩ rằng sẽ rất tốt nếu đính kèm giải pháp của mình , có lẽ nó có thể giúp đỡ những người khác trong tình huống tương tự. Trong đoạn mã Python2 này, một PCA có trọng số với nhân RBF như mô tả ở trên được sử dụng để tính các tiếp tuyến của bộ dữ liệu 2D. Tôi sẽ rất vui khi nghe một số thông tin phản hồi!
def weighted_pca_regression(x_vec, y_vec, weights):
"""
Given three real-valued vectors of same length, corresponding to the coordinates
and weight of a 2-dimensional dataset, this function outputs the angle in radians
of the line that aligns with the (weighted) average and main linear component of
the data. For that, first a weighted mean and covariance matrix are computed.
Then u,e,v=svd(cov) is performed, and u * f(x)=0 is solved.
"""
input_mat = np.stack([x_vec, y_vec])
weights_sum = weights.sum()
# Subtract (weighted) mean and compute (weighted) covariance matrix:
mean_x, mean_y = weights.dot(x_vec)/weights_sum, weights.dot(y_vec)/weights_sum
centered_x, centered_y = x_vec-mean_x, y_vec-mean_y
matrix_centered = np.stack([centered_x, centered_y])
weighted_cov = matrix_centered.dot(np.diag(weights).dot(matrix_centered.T)) / weights_sum
# We know that v rotates the data's main component onto the y=0 axis, and
# that u rotates it back. Solving u.dot([x,0])=[x*u[0,0], x*u[1,0]] gives
# f(x)=(u[1,0]/u[0,0])x as the reconstructed function.
u,e,v = np.linalg.svd(weighted_cov)
return np.arctan2(u[1,0], u[0,0]) # arctan more stable than dividing
# USAGE EXAMPLE:
# Define the kernel and make an ellipse to perform regression on:
rbf = lambda vec, stddev: np.exp(-0.5*np.power(vec/stddev, 2))
x_span = np.linspace(0, 2*np.pi, 31)+0.1
data_x = np.cos(x_span)[:-1]*20-1000
data_y = np.sin(x_span)[:-1]*10+5000
data_xy = np.stack([data_x, data_y])
stddev = 1 # a stddev of 1 in this context is highly local
for center in data_xy.T:
# weight the points based on their euclidean distance to the current center
euclidean_distances = np.linalg.norm(data_xy.T-center, axis=1)
weights = rbf(euclidean_distances, stddev)
# get the angle for the regression in radians
p_grad = weighted_pca_regression(data_x, data_y, weights)
# plot for illustration purposes
line_x = np.linspace(-5,5,10)
line_y = np.tan(p_grad)*line_x
plt.plot(line_x+center[0], line_y+center[1], c="r")
plt.scatter(*data_xy)
plt.show()
Và một đầu ra mẫu (nó làm tương tự cho mỗi dấu chấm):
Chúc mừng,
Andres