Реализация алгоритма K-SVD на Python
В настоящее время я пытаюсь применить алгоритм K-SVD с использованием Python, который основан на следующей статье здесь: http://www.cs.technion.ac.il/~elad/publications/journals/2004/32_KSVD_IEEE_TSP.pdf. До сих пор я реализовал приведенный ниже код, и он, кажется, работает довольно хорошо с точки зрения создания хорошего словаря для разреженных представлений. Код, который я создал, основан на реализации, которая существует в Python здесь, https://github.com/nel215/ksvd/blob/master/ksvd/__init__.py. Однако я изменил, поскольку я использую K-SVD для выполнения изучения словаря для сигналов другого типа по сравнению с тем, для которого предполагается использовать обычный K-SVD (я пытаюсь создать разреженный словарь для сигналов вибрации машины вместо нормальные сигналы изображения). Мой код можно увидеть ниже:
def Phi_designer_k_svd(Phi_list, y_list, index):
'''
# y_list is expected to have size of k x y_freq (k rows of y_freq sized horizontal signals)
# mp_process in here is a self-implemented OMP function, loosely following
# an implementation here: https://github.com/davebiagioni/pyomp/blob/master/omp.py
'''
# (mxn) = size of Phi
Phi = Phi_list[index]
for i in range(0,1000):
Phi_old = np.zeros(Phi.shape)
Phi_old[:, :] = Phi[:, :]
x_mp = np.zeros((n,k))
#for every column of x_mp, calculate the sparse representation of the column
#(find the representation of x_mp that would give minimum solution for ||y - Phi*x_mp||)
for j in range(0, k):
# find approximation of x signal
x_mp[:,j], _, _ = mp_process(Phi, y_cur[:,j], ncoef=sparsity, verbose=vbose)
'''for every t-th atom in Phi...
update the dictionary atoms so that it minimizes errors obtained from compressed x_mp
'''
for t in range(0, n):
#Choose the COLUMN indexes in the t-th ROW of x_mp that is NON zero!
#(synonymous with picking signals (which column) of x contributed
# directly by the t-th atom of the dictionary)
I = x_mp[t] != 0
#if there are no contributions made by this atom for x_mp, then continue to the next atom.
if np.sum(I) == 0:
continue
'''
# only columns containing nonzero elements from t-th row of x_mp is used (showing indices using t-th atom in dict),
# rest are ignored
'''
x_copy = x_mp[:, I]
#zero the t-th row as it will not be used in actual calculation
x_copy[t] = 0
#create a copy of Phi with the value of the t-th atom zeroed (to disable contribution from the t-th atom of Phi)
copy = np.zeros(Phi.shape)
copy[:] = Phi[:]
copy[:,t] = 0
#calculate error produced from contribution of t-th atom only (thus ignoring the rest of the zero elements in initial x_mp.
error = y_cur[:,I] - np.dot(copy, x_copy)
#produce a SVD decomp of the obtained error matrix
U,s,V = np.linalg.svd(error, full_matrices=True)
Phi[:, t] = U[:, 0]
'''
#update only the picked non-zero elements of x_mp (as previously mentioned) to be updated.
#(sizes of s and V should have already matched this indices group as well)
'''
x_mp[t, I] = s[0] * V[:,0]
previous_norm = l2_norm(Phi_old)
detected_norm = l2_norm(Phi)
norm_diff = previous_norm - detected_norm
#**** Convergence condition. Not sure correct or not based on paper.
if abs(norm_diff) < tol:
break
Phi_list[index] = Phi
return
Однако я обнаружил, что этот код может создать только словарь, который хорошо работает только для обучающего набора данных, а сжатие не работает для любых новых наборов данных. Я подозреваю, что, возможно, я не реализовал критерии остановки из бумаги правильно (тот, который я пометил '****' в коде выше. Последняя строка в цикле for), так как я не слишком уверен в себе какими будут соответствующие критерии остановки для алгоритма. Кто-нибудь когда-либо реализовывал свою собственную версию K-SVD на python? Если это так, я был бы очень признателен, если бы вы могли помочь мне проверить правильность моих реализованных критериев остановки и, возможно, любые дополнительные советы, которые я могу использовать, чтобы обеспечить лучшее соответствие между созданным словарем и любым новым набором сигналов.