# Which algorithm to use to classify plots based on graphical features?

I have plots which I need to classify based on some features. For example, I need to differentiate between the following plots having smooth features or 'valleys' at certain x values. Which machine learning algorithm would be most appropriate to do so? I was thinking a combination of anomaly detection, clustering and classification. Any help is appreciated. Thank you!

Your question is unclear. Please provide more information about the dataset, the dataset size, the target, the motivation. Until then I can only assume and try to help nontheless.

Assumptions

Since you speak of classification I assume that you have labels. I further assume that you have access to the underlying data used to produce the plot. In that exact case, the following will be useful:

Solution

Instead of classifying the plots, you could classify the underlying two-dimensional datasets treating them as time-series.

For your specific case, Dynamic Time Warping distance could be useful. You could therefore use this code:

import numpy as np
from scipy.spatial import distance
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report

#toy dataset
X = np.random.random((100,10))
y = np.random.randint(0,2, (100))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

#custom metric
def DTW(a, b):
an = a.size
bn = b.size
pointwise_distance = distance.cdist(a.reshape(-1,1),b.reshape(-1,1))
cumdist = np.matrix(np.ones((an+1,bn+1)) * np.inf)
cumdist[0,0] = 0

for ai in range(an):
for bi in range(bn):
minimum_cost = np.min([cumdist[ai, bi+1],
cumdist[ai+1, bi],
cumdist[ai, bi]])
cumdist[ai+1, bi+1] = pointwise_distance[ai,bi] + minimum_cost

return cumdist[an, bn]

#train
parameters = {'n_neighbors':[2, 4, 8]}
clf = GridSearchCV(KNeighborsClassifier(metric =DTW), parameters, cv=5)
clf.fit(X_train, y_train)

#evaluate
y_pred = clf.predict(X_test)
print(classification_report(y_test, y_pred))


For starters, the valleys or straight segments are not defined at any particular point, but at range of points - or line (curve) segments. Starting point could be separating N line segments with each being M km length, where N and M are depend on your choice. This will give you a representation of each graph as several smaller graphs.

Then it comes to the labelling those smaller graphs. For this purpose, clustering might work, but in addition to valleys and smooth section classes, we need to take into account other potential shapes, such as the uphill section in 23-35 km of the first graph. If the ending of all graphs are like given in the figures above - smoothing out at a higher value towards the end, this should cover all the classes. It is probably not the best approach but worth a try.