92 lines
4.6 KiB
Python
92 lines
4.6 KiB
Python
from tslearn.clustering import TimeSeriesKMeans
|
||
from tslearn.metrics import lb_keogh as Keogh
|
||
from sklearn.neighbors import KNeighborsClassifier,NearestNeighbors
|
||
from numpy.linalg import norm
|
||
from tslearn.metrics import dtw
|
||
|
||
class IVFADC_DTW():
|
||
def k_means(X,n,iter):
|
||
model = TimeSeriesKMeans(n_clusters=n, metric='dtw',random_state=0,max_iter=iter)
|
||
model.fit(X)
|
||
cluster=model.cluster_centers_
|
||
clusters=[]
|
||
for c in cluster:
|
||
c=list(c.reshape(1,-1))
|
||
c=c[0]
|
||
clusters.append(c)
|
||
clusters=np.array(clusters)
|
||
return clusters
|
||
def dtw(A,B):
|
||
return dtw(A, B, global_constraint="itakura", itakura_max_slope=2.)
|
||
def PQ(X,main_clusters,n_clusters,m_clusters,m):
|
||
database=[[] for _ in range(n_clusters)]
|
||
subvectors = [] # подвекторы
|
||
nn_main_res = [] # чтобы знать результаты поиска главных центроидов
|
||
nn = NearestNeighbors(n_neighbors=n_clusters,metric=IVFADC_DTW.dtw) # создаем поиск ближайших главных центроидов
|
||
nn.fit(main_clusters) # обучаем его
|
||
for x in X: # для каждого вектора в X
|
||
res=nn.kneighbors([x],n_neighbors=n_clusters,return_distance=False) # находим ближайший к нему центроид
|
||
res=res[0][0]
|
||
nn_main_res.append(res) # заносим результат во временное хранилище
|
||
x-=main_clusters[res] # вычисляем остаток
|
||
D = len(x)
|
||
assert D % m == 0
|
||
D_ = int(D / m)
|
||
x_sub = [x[row:row+D_] for row in range(0, D, D_)] # делаем нарезку
|
||
for sub in x_sub:
|
||
subvectors.append(sub) # добавляем подвекторы в общую базу
|
||
del x_sub,D,D_,res,nn,X
|
||
subvectors=np.array(subvectors)
|
||
print(len(nn_main_res))
|
||
print('Подвекторы созданы')
|
||
sub_clusters=IVFADC_DTW.k_means(subvectors,m_clusters,10) # создаем кластеры для подвекторов
|
||
print('Кластеры для подвекторов созданы')
|
||
nn = NearestNeighbors(n_neighbors=m_clusters,metric=IVFADC_DTW.dtw) # создаем поиск ближайших подцентроидов
|
||
nn.fit(sub_clusters) # учим его
|
||
print('NN для подкластеров создан')
|
||
code=[] # переменная для формирования кода PQ
|
||
q=0
|
||
k=0
|
||
print(len(subvectors))
|
||
for sub in subvectors:
|
||
k+=1
|
||
res=nn.kneighbors([sub],n_neighbors=m_clusters,return_distance=False) # находим ближайший центроид
|
||
res=res[0][0]
|
||
if k!=m:
|
||
code.append(res) # формируем код
|
||
else:
|
||
code.append(res)
|
||
ind = nn_main_res[q]
|
||
database[ind].append([q,code])
|
||
print(q,code,m)
|
||
code=[]
|
||
q+=1
|
||
k=0
|
||
return database, sub_clusters
|
||
|
||
def train(X,n_clusters,m_clusters,m):
|
||
main_clusters=IVFADC_DTW.k_means(X,n_clusters,30)
|
||
print('Главные кластеры созданы')
|
||
database,sub_clusters=IVFADC_DTW.PQ(X,main_clusters,n_clusters,m_clusters,m)
|
||
return [main_clusters,sub_clusters,database]
|
||
def predict(x,w,k,m,index):
|
||
nn = NearestNeighbors(n_neighbors=w,metric=IVFADC_DTW.dtw) # создаем поиск ближайших главных центроидов
|
||
nn.fit(index[0]) # обучаем его
|
||
res=nn.kneighbors([x],n_neighbors=w,return_distance=False) # находим ближайшие w центроидов
|
||
res=res[0]
|
||
v_dists=[]
|
||
for r in res:
|
||
remain=x-np.array(index[0][r])
|
||
D = len(remain)
|
||
D_ = int(D/m)
|
||
x_sub = [remain[row:row+D_] for row in range(0, D, D_)] # делаем нарезку получаем векторы w векторов разбитых на 11 подвекторов длинной 5
|
||
for vector in index[2][r]:
|
||
dist=0
|
||
code=vector[1]
|
||
for i in range(len(code)):
|
||
dist+=IVFADC_DTW.dtw(x_sub[i],index[1][code[i]])
|
||
v_dists.append([vector[0],dist])
|
||
v_dists=sorted(v_dists, key=lambda x: x[1])
|
||
v_dists=v_dists[:k]
|
||
return v_dists
|