carterwward
commited on
Commit
•
38096b2
1
Parent(s):
c9da403
add direction tracking functionality to evolutionary algorithm, updat git ignore
Browse files- .gitignore +2 -0
- my_cache_handler.py +0 -3
- src/evolutionary_alrogithm.py +46 -1
.gitignore
CHANGED
@@ -7,3 +7,5 @@
|
|
7 |
/data/songs_new.csv
|
8 |
__pycache__
|
9 |
*.code-workspace
|
|
|
|
|
|
7 |
/data/songs_new.csv
|
8 |
__pycache__
|
9 |
*.code-workspace
|
10 |
+
imgs/
|
11 |
+
.DS_Store
|
my_cache_handler.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
from spotipy.cache_handler import CacheHandler
|
2 |
-
|
3 |
-
class CacheFileHandler(CacheHandler):
|
|
|
|
|
|
|
|
src/evolutionary_alrogithm.py
CHANGED
@@ -1,14 +1,18 @@
|
|
1 |
import pandas as pd
|
2 |
import numpy as np
|
|
|
|
|
3 |
import gradio as gr
|
4 |
import plotly.express as px
|
5 |
from plotly.graph_objects import Figure
|
|
|
6 |
from copy import deepcopy
|
7 |
from random import choice
|
8 |
from typing import List, Set
|
9 |
import itertools
|
10 |
from sklearn.preprocessing import StandardScaler
|
11 |
from src.spotipy_utils import SpotifyTrack, get_sp_client
|
|
|
12 |
|
13 |
# Initial data cleaning.
|
14 |
SONG_DF = pd.read_csv("data/SpotifyAudioFeaturesApril2019.csv")
|
@@ -127,7 +131,7 @@ class Population:
|
|
127 |
self.crossover_function = crossover_function
|
128 |
self.mutation_size = mutation_size
|
129 |
self.history_df = deepcopy(history_df)
|
130 |
-
|
131 |
|
132 |
def mutate(self, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
133 |
""" Method to call assigned mutation function through.
|
@@ -201,6 +205,35 @@ class Population:
|
|
201 |
},)
|
202 |
|
203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
def update_population_history(self, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
205 |
""" Update the DF keeping track of the traversal history.
|
206 |
|
@@ -283,11 +316,17 @@ def simple_mutation(population: Population, thumbs_up:List[Individual], thumbs_d
|
|
283 |
"""
|
284 |
liked_tracks = list(itertools.chain(*[thumbs_up, added_songs]))
|
285 |
new_track_inds = set()
|
|
|
|
|
286 |
for i in range(population.size):
|
287 |
liked_track = choice(liked_tracks)
|
288 |
mutated_track_genome = liked_track.genome + np.random.uniform(size=(population.size))*population.mutation_size
|
289 |
child = get_closest_song_to_genome(population, mutated_track_genome, new_track_inds)
|
|
|
|
|
290 |
population.pop[i] = child
|
|
|
|
|
291 |
|
292 |
|
293 |
def differential_mutation(population: Population, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
@@ -300,6 +339,8 @@ def differential_mutation(population: Population, thumbs_up:List[Individual], th
|
|
300 |
added_songs (List[Individual]): List of individuals added to the playlist.
|
301 |
"""
|
302 |
new_track_inds = set()
|
|
|
|
|
303 |
for i in range(population.size):
|
304 |
if thumbs_down:
|
305 |
disliked_track = choice(thumbs_down)
|
@@ -321,4 +362,8 @@ def differential_mutation(population: Population, thumbs_up:List[Individual], th
|
|
321 |
gene_distances = attracting_track.genome - disliked_track.genome
|
322 |
resulting_genome = seed_track.genome + gene_distances*population.mutation_size
|
323 |
child = get_closest_song_to_genome(population, resulting_genome, new_track_inds)
|
|
|
|
|
324 |
population.pop[i] = child
|
|
|
|
|
|
1 |
import pandas as pd
|
2 |
import numpy as np
|
3 |
+
from scipy.spatial.distance import cosine
|
4 |
+
import scikits.bootstrap as bootstrap
|
5 |
import gradio as gr
|
6 |
import plotly.express as px
|
7 |
from plotly.graph_objects import Figure
|
8 |
+
import matplotlib.pyplot as plt
|
9 |
from copy import deepcopy
|
10 |
from random import choice
|
11 |
from typing import List, Set
|
12 |
import itertools
|
13 |
from sklearn.preprocessing import StandardScaler
|
14 |
from src.spotipy_utils import SpotifyTrack, get_sp_client
|
15 |
+
# plt.switch_backend('Agg') # NOTE: for traversal direction tracking viz
|
16 |
|
17 |
# Initial data cleaning.
|
18 |
SONG_DF = pd.read_csv("data/SpotifyAudioFeaturesApril2019.csv")
|
|
|
131 |
self.crossover_function = crossover_function
|
132 |
self.mutation_size = mutation_size
|
133 |
self.history_df = deepcopy(history_df)
|
134 |
+
self.distance_matrices = []
|
135 |
|
136 |
def mutate(self, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
137 |
""" Method to call assigned mutation function through.
|
|
|
205 |
},)
|
206 |
|
207 |
|
208 |
+
def generate_direction_tracking(self):
|
209 |
+
multidim_distance = np.stack(self.distance_matrices, axis=2)
|
210 |
+
|
211 |
+
# Compute distribution of cosine similarity amongst distance vectors between individuals of the same generation.
|
212 |
+
sibling_directional_similarity = np.zeros((multidim_distance.shape[2], multidim_distance.shape[0]*(multidim_distance.shape[0]-1)))
|
213 |
+
for t in range(multidim_distance.shape[2]):
|
214 |
+
cosine_similarities = []
|
215 |
+
for i in range(multidim_distance.shape[0]):
|
216 |
+
for j in range(multidim_distance.shape[0]):
|
217 |
+
if i == j:
|
218 |
+
continue
|
219 |
+
|
220 |
+
cosine_similarity = cosine(multidim_distance[i,:,t], multidim_distance[j,:,t])
|
221 |
+
|
222 |
+
cosine_similarities.append(cosine_similarity)
|
223 |
+
|
224 |
+
sibling_directional_similarity[t, :] = np.array(cosine_similarities)
|
225 |
+
num_obs = sibling_directional_similarity.shape[0]
|
226 |
+
# Compute bootstrapped CI
|
227 |
+
data_ci = [bootstrap.ci(sibling_directional_similarity[k, :]) for k in range(num_obs)]
|
228 |
+
means = [ci.sum() / 2 for ci in data_ci]
|
229 |
+
lower = [ci[0] for ci in data_ci]
|
230 |
+
upper = [ci[1] for ci in data_ci]
|
231 |
+
|
232 |
+
plt.plot(means, label = "Distribution of Cosine Similarity for Paternal Distance Vectors Among Siblings Over Time")
|
233 |
+
plt.fill_between(np.arange(num_obs), upper, lower, alpha = 0.5)
|
234 |
+
plt.savefig("cosine_dist_over_time.png")
|
235 |
+
|
236 |
+
|
237 |
def update_population_history(self, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
238 |
""" Update the DF keeping track of the traversal history.
|
239 |
|
|
|
316 |
"""
|
317 |
liked_tracks = list(itertools.chain(*[thumbs_up, added_songs]))
|
318 |
new_track_inds = set()
|
319 |
+
# Init population distance matrix
|
320 |
+
distance_matrix = np.zeros((population.size, population.size))
|
321 |
for i in range(population.size):
|
322 |
liked_track = choice(liked_tracks)
|
323 |
mutated_track_genome = liked_track.genome + np.random.uniform(size=(population.size))*population.mutation_size
|
324 |
child = get_closest_song_to_genome(population, mutated_track_genome, new_track_inds)
|
325 |
+
# Record distance vector for parent-child.
|
326 |
+
distance_matrix[i, :] = child.genome - liked_track.genome
|
327 |
population.pop[i] = child
|
328 |
+
# Add to distance matrix tracking list.
|
329 |
+
population.distance_matrices.append(distance_matrix)
|
330 |
|
331 |
|
332 |
def differential_mutation(population: Population, thumbs_up:List[Individual], thumbs_down:List[Individual], added_songs:List[Individual]):
|
|
|
339 |
added_songs (List[Individual]): List of individuals added to the playlist.
|
340 |
"""
|
341 |
new_track_inds = set()
|
342 |
+
# Init population distance matrix
|
343 |
+
distance_matrix = np.zeros((population.size, population.size))
|
344 |
for i in range(population.size):
|
345 |
if thumbs_down:
|
346 |
disliked_track = choice(thumbs_down)
|
|
|
362 |
gene_distances = attracting_track.genome - disliked_track.genome
|
363 |
resulting_genome = seed_track.genome + gene_distances*population.mutation_size
|
364 |
child = get_closest_song_to_genome(population, resulting_genome, new_track_inds)
|
365 |
+
# Record distance vector for parent-child.
|
366 |
+
distance_matrix[i, :] = child.genome - attracting_track.genome
|
367 |
population.pop[i] = child
|
368 |
+
# Add to distance matrix tracking list.
|
369 |
+
population.distance_matrices.append(distance_matrix)
|