Выбор функций является важной частью любого проекта машинного обучения, неправильный выбор функций, которые будут использоваться моделью, может привести к худшим результатам, поскольку для получения оптимального набора функций было разработано множество методов и методов.
В случае обучения с учителем эта задача относительно проста благодаря ранее существовавшим уловкам, таким как важность функций, встроенная во многие модели обучения scikit perse (например, случайный Форрест, линейная регрессия, логистическая регрессия и т. д.), и существование вычислимых функций потерь напрямую также очень помогает, так как мы всегда можем выполнить исчерпывающий поиск с фиксированной моделью и сравнить полученные оценки потерь.
Тем не менее, реальная проблема заключается в случае обучения без учителя, когда такие методы не очень интуитивны. В дальнейшем в этой статье я буду демонстрировать технику, которую я использовал в недавнем проекте для выполнения выбора функций в случае обучения без учителя.
Данные конфиденциальны, поэтому я не могу ими поделиться, тем не менее, я могу поделиться техникой, которую использовал, так как она открыта и доступна онлайн.
Первое, с чем нужно ознакомиться, это PCA или анализ основных компонентов.
Основные компоненты набора точек в реальном координатном пространстве — это последовательность n единичных векторов, где i-й вектор — это направление линии, которая лучше всего соответствует данным, будучи ортогональной первым i-1 векторам. Эти направления образуют ортонормированный базис. Анализ основных компонентов (PCA) — это процесс вычисления основных компонентов и их использования для изменения базы данных. (см. https://en.wikipedia.org/wiki/Principal_component_analysis)
Что мы хотим сделать, так это построить объясненную дисперсию каждого компонента (см. статью, упомянутую выше).
from sklearn.decomposition import PCA pca = PCA() pca.fit(df) df_pca_all = pca.transform(df) eigenvalues = pca.explained_variance_ plt.bar(np.arange(0,df.shape[1],1), eigenvalues) plt.plot(eigenvalues, "r") plt.plot(eigenvalues, "ro") plt.show()
Так, например, если бы это были наши данные, мы могли бы сказать, что объясненная дисперсия в основном переносится первым и вторым компонентами, и, таким образом, мы можем спроецировать наши данные на эти оси, следовательно, на новую основу.
Давайте спроецируем данные и посмотрим, что произойдет
Теперь, очевидно, мы можем видеть некоторые выбросы здесь и там, чтобы справиться с ними, мы применим изолирующий лес, который будет автоматически обнаруживать аномалии, следовательно, выбросы.
from sklearn.ensemble import IsolationForest rng = np.random.RandomState(42) clf = IsolationForest(n_estimators=1000, random_state=rng) #df_pca is the new projected data clf.fit(df_pca) IF_labels = clf.predict(df_pca) plt.scatter(df_pca[:, 0], df_pca[:, 1], c=IF_labels, s=40, cmap='viridis')
Теперь, когда наши данные очищены, мы можем обсудить слона в комнате: выбор признаков в неконтролируемом обучении.
Нашим основным инструментом будет анализ основных признаков, для объяснения которого мы возьмем несколько абзацев из этой статьи: http://www.ifp.illinois.edu/~qitian/e_paper/icip02/icip02.pdf.
Вот как все это переводится в строки кода:
from collections import defaultdict from sklearn.metrics.pairwise import euclidean_distances from sklearn.preprocessing import StandardScaler class PFA(object): def __init__(self, n_features, q=None): self.q = q self.n_features = n_features def fit(self, X): if not self.q: self.q = X.shape[1] X = np.array(X) sc = StandardScaler() # X = sc.fit_transform(X) pca = PCA(n_components=self.q).fit(X) # calculation Cov matrix is embeded in PCA A_q = pca.components_.T kmeans = KMeans(n_clusters=self.n_features).fit(A_q) clusters = kmeans.predict(A_q) cluster_centers = kmeans.cluster_centers_ dists = defaultdict(list) for i, c in enumerate(clusters): dist = euclidean_distances([A_q[i, :]], [cluster_centers[c, :]])[0][0] dists[c].append((i, dist)) self.indices_ = [sorted(f, key=lambda x: x[1])[0][0] for f in dists.values()] self.features_ = X[:, self.indices_] #Run exhaustive search to find the best features to keep: def get_key(val,y): for key, value in Counter(y).items(): if val == value: return key return "key doesn't exist" p = 1 #n will be the number of features you have n = 50 for k in range(2,n,1): print('########## K = ',k,' #######') pfa = PFA(n_features=k) pfa.fit(df) # To get the transformed matrix x = pfa.features_ rng = np.random.RandomState(42) clf = IsolationForest(n_estimators=1000, random_state=rng) clf.fit(x) IF_labels = clf.predict(x) m = get_key(max(Counter(IF_labels).values()),IF_labels) x = pd.DataFrame(x) x['outliers'] = IF_labels x = x[x['outliers'] == m ] x = x.drop(columns = 'outliers') x = np.array(x) pca.fit(x) x = pca.transform(x) model_agg_clustering = AgglomerativeClustering(n_clusters=3) # fit model and predict clusters yhat_agg_clustering = model_agg_clustering.fit_predict(x) print('agglomerative') model_birch = Birch(threshold=0.01, n_clusters=3) # fit the model model_birch.fit(x) # assign a cluster to each example yhat_birch = model_birch.predict(x) model_mb_km = MiniBatchKMeans(n_clusters=3) # fit the model model_mb_km.fit(x) # assign a cluster to each example print('Mini Batch Kmeans') yhat_mb_km = model_mb_km.predict(x) label_list = [yhat_agg_clustering, yhat_birch, yhat_mb_km] models = ['AgglomerativeClustering', 'BIRCH', 'MiniBatch_KMeans'] for idx,labels in enumerate(label_list): silhouette_avg = silhouette_score(x, labels) print("The average silhouette_score for", models[idx], " is :", silhouette_avg)
Как видите, мы выполнили исчерпывающий поиск, чтобы определить наилучшую комбинацию модели и характеристик с точки зрения оценки силуэта.
Я надеюсь, что вы нашли эту короткую статью полезной для своих проектов, и я не беру на себя ответственность за упомянутые выше алгоритмы, поскольку они были разработаны благодаря тяжелой работе ученых, которые их изобрели.