X-Git-Url: https://code.communitydata.science/cdsc_reddit.git/blobdiff_plain/56269deee3d33620550d67bdd3c1a7b64eb3f7e4..f05cb962e0388feaf38aaf84f222696ab8f5f398:/clustering/clustering.py?ds=inline diff --git a/clustering/clustering.py b/clustering/clustering.py old mode 100644 new mode 100755 index e652304..6ee7842 --- a/clustering/clustering.py +++ b/clustering/clustering.py @@ -1,28 +1,35 @@ #!/usr/bin/env python3 - +# TODO: replace prints with logging. +import sys import pandas as pd import numpy as np from sklearn.cluster import AffinityPropagation import fire - -def affinity_clustering(similarities, output, damping=0.9, max_iter=100000, convergence_iter=30, preference_quantile=0.5, random_state=1968, verbose=True): +from pathlib import Path +from multiprocessing import cpu_count +from dataclasses import dataclass +from clustering_base import sim_to_dist, process_clustering_result, clustering_result, read_similarity_mat + +def affinity_clustering(similarities, output, *args, **kwargs): + subreddits, mat = read_similarity_mat(similarities) + clustering = _affinity_clustering(mat, *args, **kwargs) + cluster_data = process_clustering_result(clustering, subreddits) + cluster_data['algorithm'] = 'affinity' + return(cluster_data) + +def _affinity_clustering(mat, subreddits, output, damping=0.9, max_iter=100000, convergence_iter=30, preference_quantile=0.5, random_state=1968, verbose=True): ''' - similarities: feather file with a dataframe of similarity scores + similarities: matrix of similarity scores preference_quantile: parameter controlling how many clusters to make. higher values = more clusters. 0.85 is a good value with 3000 subreddits. damping: parameter controlling how iterations are merged. Higher values make convergence faster and more dependable. 0.85 is a good value for the 10000 subreddits by author. ''' - - df = pd.read_feather(similarities) - n = df.shape[0] - mat = np.array(df.drop('subreddit',1)) - mat[range(n),range(n)] = 1 + print(f"damping:{damping}; convergenceIter:{convergence_iter}; preferenceQuantile:{preference_quantile}") preference = np.quantile(mat,preference_quantile) print(f"preference is {preference}") - print("data loaded") - + sys.stdout.flush() clustering = AffinityPropagation(damping=damping, max_iter=max_iter, convergence_iter=convergence_iter, @@ -32,22 +39,14 @@ def affinity_clustering(similarities, output, damping=0.9, max_iter=100000, conv verbose=verbose, random_state=random_state).fit(mat) + cluster_data = process_clustering_result(clustering, subreddits) + output = Path(output) + output.parent.mkdir(parents=True,exist_ok=True) + cluster_data.to_feather(output) + print(f"saved {output}") + return clustering - print(f"clustering took {clustering.n_iter_} iterations") - clusters = clustering.labels_ - - print(f"found {len(set(clusters))} clusters") - - cluster_data = pd.DataFrame({'subreddit': df.subreddit,'cluster':clustering.labels_}) - - cluster_sizes = cluster_data.groupby("cluster").count() - print(f"the largest cluster has {cluster_sizes.subreddit.max()} members") - - print(f"the median cluster has {cluster_sizes.subreddit.median()} members") - - print(f"{(cluster_sizes.subreddit==1).sum()} clusters have 1 member") - cluster_data.to_feather(output) if __name__ == "__main__": fire.Fire(affinity_clustering)