Source code for queso_cluster.atoms.scores

import numpy as np
#import dask.array as da
import numba as nb

from . import base as baseAtom

from ..addon import logg
# def calcResolvingIndex(dataSquare, labelLine):
# 	labelLst = np.unique(labelLine)
# 	resolveSquare = np.zeros((len(labelLst), dataSquare.shape[1]))
# 	for l in range(labelLst.size):
# 		lindx = np.where(labelLine == labelLst[l])[0]
# 		resolveSquare[l, :] = calcSingleResolvingIndex(dataSquare[lindx, :])

# 	return(resolveSquare)		

# def calcSingleResolvingIndex(dataSquare):

# 	centroid_mins, centroid_plus = np.quantile(dataSquare, [0.25, 0.75], axis=0)
# 	centroid = dataSquare.sum(axis=0)/dataSquare.shape[0]
# 	# centroid_plus = dataSquare.max(axis=0)
# 	# centroid_mins = dataSquare.min(axis=0)
	
# 	plusIndx = np.where(dataSquare > centroid_plus)[0]
# 	centroid_plus = dataSquare[plusIndx, :].sum()/plusIndx.size

# 	minsIndx = np.where(dataSquare < centroid_mins)[0]
# 	centroid_mins = dataSquare[minsIndx, :].sum()/minsIndx.size

# 	delta_plus = np.abs(centroid_plus - centroid)
# 	delta_mins = np.abs(centroid_mins - centroid)

# 	return((delta_plus - delta_mins)/(delta_plus + delta_mins))
	

# @nb.njit()
# def calcElbowEntry(data, labels):
# 	#> detail: 
# 	#> param type data:
# 	#> param type labels:
# 	#> return (type): 
# 	#> test-method:

# 	labelLst = np.unique(labels)
# 	localDistance = np.zeros(len(labelLst))
# 	for j in range(len(labelLst)):
# 		indx = np.where(labels == labelLst[j])[0]
# 		centroid = data[indx, :].sum(axis=0)/len(indx)
# 		d2 = 0.0
# 		for k in range(len(indx)):
# 			d = data[indx[k], :] - centroid
# 			d2 += np.sqrt(d.dot(d))
# 		#print(d2/len(indx))
# 		localDistance[j] = d2/len(indx)

# 	# def _calcScore(scores):
# 	# 	return(np.argmax(np_gradient(np_gradient(_calcCurvature(scores)))) + 1)

# 	return(localDistance)#, _calcScore)

# # @nb.njit()
# # def calcVarianceScore(data):
# # 	#> detail: 
# # 	#> param type data:
# # 	#> return (type): 
# # 	#> test-method:

# # 	avg_var = np.std(data, axis=0).sum()/data.shape[1]
# # 	centroid = data.sum(axis=0)/data.shape[0]

# @nb.njit()
# def criteriaInertiaScore(score):
# 	#> detail: 
# 	#> param type score:
# 	#> return (type): 
# 	#> test-method:
# 	diff = baseAtom.np_gradient(score)
# 	for d in range(diff.size):
# 		if diff[d] < diff[0]*0.8:
# 			return d		

# @nb.njit()
# def calcInertiaScore(dataSquare, labelLine):
# 	#> detail: 
# 	#> param type dataSquare:
# 	#> param type labelLine:
# 	#> return (type): 
# 	#> test-method:
# 	labelLst = np.unique(labelLine)
# 	inertia = 0
# 	for l in range(labelLst.size):
# 		lindx = np.where(labelLine == labelLst[l])[0]
# 		centroid = dataSquare[lindx, :].sum(axis=0)/labelLst.size
# 		for ll in range(lindx.size):
# 			delta = dataSquare[lindx[ll], :] - centroid
# 			inertia += delta.dot(delta)
# 	return(inertia)	

# @nb.njit()
# def criteriaSilhouetteScore(score):
# 	#> detail: 
# 	#> param type score:
# 	#> return (type): 
# 	#> test-method:
# 	return(score.argmax())


# @nb.njit(cache=True)
# def calcNeighborSilhouetteScore(dataSquare, labelLine, point=None, unbound=False):
# 	labelLst = np.unique(labelLine)
# 	scores = np.zeros(labelLst.size)

# 	if not (point is None):
# 		labelLst = np.asarray([point])

# 	for l in range(labelLst.size):
# 		#scores[l] = calcNeighborSingleSilhouetteScore(dataSquare, labelLine, 
# 		#										labelLst[l], unbound)
# 		intraIndxs = np.where(labelLine == labelLst[l])[0]

# 		sampleScore = np.zeros(intraIndxs.size)

# 		for j in range(intraIndxs.size):
# 			intraIndx = intraIndxs[j]
# 			neighbor = findSampleNeighbor(dataSquare, labelLine, intraIndx)

# 			interIndxs = np.where(labelLine == neighbor)[0]
			
# 			intraSample = dataSquare[intraIndx, :]#.sum(axis=0)/len(intraIndx)

# 			intra_d2 = 0.0
# 			for k in range(len(intraIndxs)):
# 				d = dataSquare[intraIndxs[k], :] - intraSample
# 				intra_d2 += np.sqrt(d.dot(d))		
			
# 			inter_d2 = 0.0
# 			for k in range(len(interIndxs)):
# 				d = dataSquare[interIndxs[k], :] - intraSample
# 				inter_d2 += np.sqrt(d.dot(d))

# 			intraDistance = intra_d2/(len(intraIndxs)-1)
# 			interDistance = inter_d2/len(interIndxs)

# 			if unbound:
# 				sampleScore[j] = 1 - intraDistance/interDistance
# 			else:
# 				sampleScore[j] = (interDistance - intraDistance)/np.maximum(intraDistance, interDistance)

# 		scores[l] = sampleScore.mean()

# 		if point == labelLst[l]:
# 			return(scores[l])
		
# 	return(scores.min())


[docs] @nb.njit(cache=True) def speedTest2(intraSamples, intraIndxSize, i): intra_d2 = 0.0 for j in range(intraIndxSize): if j == i: continue d = intraSamples[j, :] - intraSamples[i, :] intra_d2 += np.sqrt(d.dot(d)) return(intra_d2/intraIndxSize)
[docs] @nb.njit(cache=True) def speedTest(interSamples, intraSample, interIndxSize): inter_d2 = 0.0 for k in range(interIndxSize): d = interSamples[k, :] - intraSample inter_d2 += np.sqrt(d.dot(d)) return(inter_d2/interIndxSize)
[docs] @nb.njit(cache=True) def findSampleNeighbor(dataSquare, labelLine, pointIndx): """ Calculates the nearest label to a given sample Parameters ---------- dataSquare : ndarray 2D array (nsamples, nfeatures) containing the pool of data labelLine : ndarray 1D array (nsamples,) for the labels on the data pointIndx : int sample index Returns ------- int The label of the nearest cluster to that point """ store = np.zeros((dataSquare.shape[0])) + np.inf interIndx = np.where(labelLine != labelLine[pointIndx])[0] for l in range(interIndx.size): delta = dataSquare[pointIndx, :] - dataSquare[interIndx[l], :] store[interIndx[l]] = np.sqrt(delta.dot(delta)) neighborLabel = labelLine[np.argmin(store)] return(neighborLabel)
[docs] @logg.loggTimer @nb.njit(cache=True) def calcNeighborSilhouetteScore(dataSquare, labelLine, point): """ Calculates the Silhouette Score for a specific cluster Parameters ----------- dataSquare : ndarray 2D array (nsamples, nfeatures) containing the pool of data labelLine : ndarray 1D array (nsamples,) for the labels on the data point : int cluster label to evaluate Returns ------- int Silhouette Score """ intraIndxs = np.where(labelLine == point)[0] score = np.zeros(intraIndxs.size) for i in range(intraIndxs.size): neighbor = findSampleNeighbor(dataSquare, labelLine, intraIndxs[i]) interIndxs = np.where(labelLine == neighbor)[0] intraSamples = dataSquare[intraIndxs, :] interSamples = dataSquare[interIndxs, :] # intra_d2 = 0.0 # for j in range(intraIndxs.size): # if j == i: # continue # d = intraSamples[j, :] - intraSamples[i, :] # intra_d2 += np.sqrt(d.dot(d)) intraDistance = speedTest2(intraSamples, intraIndxs.size, i) interDistance = speedTest(interSamples, intraSamples[i, :], interIndxs.size) # inter_d2 = 0.0 # for k in range(interIndxs.size): # d = interSamples[k, :] - intraSamples[i, :] # inter_d2 += np.sqrt(d.dot(d)) #intraDistance = intra_d2/(intraIndxs.size-1) #interDistance = inter_d2/interIndxs.size #if unbound: score[i] = 1 - intraDistance/interDistance #else: #@score[i] = (interDistance - intraDistance)/np.maximum(intraDistance, interDistance) return(np.median(score))
[docs] @nb.njit() def calcDaviesBouldin(data, labels, q=2): labelLst = np.unique(labels) Ri = np.zeros(labelLst.size) for i in range(labelLst.size): intraIndx = np.where(labels == labelLst[i])[0] intraCentroid = data[intraIndx, :].sum(axis=0)/len(intraIndx) si = 0.0 for k in range(len(intraIndx)): d = data[intraIndx[k], :] - intraCentroid si += np.sqrt(d.dot(d)) si /= intraIndx.size Rij = np.zeros(labelLst.size) + np.nan for j in range(labelLst.size): if i == j: continue interIndx = np.where(labels == labelLst[j])[0] interCentroid = data[interIndx, :].sum(axis=0)/interIndx.size sj = 0.0 for k in range(len(interIndx)): d = data[interIndx[k], :] - interCentroid sj += np.sqrt(d.dot(d)) sj /= interIndx.size dij = intraCentroid - interCentroid dij = np.sqrt(dij.dot(dij)) Rij[j] = (si + sj) / dij Ri[i] = np.nanmax(Rij) return(Ri.sum()/labelLst.size)
# @nb.njit() # def calcCHindex(data, labels): # #> detail: # #> param type data: # #> param type labels: # #> return (type): # #> test-method: # N = data.shape[0] # K = len(np.unique(labels)) # labelLst = np.unique(labels) # if len(labelLst) == 1: # return(np.nan) # wgss = np.zeros(len(labelLst)) #+ np.nan # bgss = np.zeros(len(labelLst))# np.nan # for k in range(len(labelLst)): # intraIndx = np.where(labels == labelLst[k])[0] # interIndx = np.where(labels != labelLst[k])[0] # intra_centroid = data[intraIndx, :].sum(axis=0)/len(intraIndx) # intra_d2 = 0.0 # for i in range(len(intraIndx)): # d = data[intraIndx[i], :] - intra_centroid # intra_d2 += d.dot(d) # inter_centroid = (data[interIndx, :].sum(axis=0) + data[intraIndx, :].sum(axis=0))/(len(intraIndx) + len(interIndx)) # # print(inter_centroid) # d = inter_centroid - intra_centroid # bgss[k] = nb.float32(len(intraIndx) * d.dot(d)) # wgss[k] = nb.float32(intra_d2)#/len(intraIndx) # return((bgss.sum()/wgss.sum()) * (N - K)/(K - 1))