<jupyter_start><jupyter_text>O TuneMyMood é um projeto da matéria de Ciência dos Dados feito por alunos do segundo semestre de Engenharia de Computação no Insper. O projeto consiste em utilizar de classificadores, como Naive-Bayes e Support Vector Classification(Classificação de Suporte Vetorial), __para conseguir separar músicas por gênero musical e moods(humores)__ com base nos dados, recolhidos pelo Spotipy, uma biblioteca em python que se comunica com a WEB API do serviço de streaming de música Spotify, de: - acousticness(indice de 0 a 1 que representa o quão acústica é uma música), - danceability(índice de 0 a 1 que representa o quão boa uma música é para dançar), - instrumentalness(íncide de 0 a 1 que representa o quão próxima uma música chega de ser totalmente intrumental, sendo que sons como "Ooh" e "Aah" são considerados instrumentais), - key(Representa o tom na qual a música é tocada, começando da seguinte maneira: Dó=1, Ré=2, Mi=3, etc.), - liveness(Índice de 0 a 1 que representa o quão ao vivo uma música é, baseada em ruídos externos), - loudness(Índice de 0 a 1 que representa o quão barulhenta uma música é), - mode(Representa tons maiores ou menores. Exemplo: Dó maior = 1, Ré menor = 0), - speechiness(Índice de 0 a 1 que representa o quanto da música são palavras faladas ao invés de cantadas), - tempo(Representa o número de batidas por minuto da música, ou em outras palavras, o quão rápida ela é), - time_signature(Índice que representa o compasso da música, fração que representa o agrupamento de sons de uma música. Estilos diferentes costumam ter compassos específicos, como o compasso na valsa que é 3/4), - valence(Índice de 0 a 1 que representa o humor de uma música, sendo 0 uma música triste e 1 uma feliz) Divisão de funções:_Arthur Olga_:Coleta de dados e API do SpotifyModelagem das funções de download e classificação de DatasetsRelatórioExplicação de conceitos_<NAME>_:Modelagem das funções de classificadores/treinadores e DatasetsLapidação dos modelosImplementação de conceitos como Treshold e SVCCriação do modelo DatasetsOrganização do código  Link para os atributos de uma música: https://developer.spotify.com/web-api/get-audio-features/  Índice 1.0 Utilizando a API Spotipy 2.0 Entendendo nossos classificadores 2.1 Classificador de Naive-Bayes 2.2 SVC - Classificador por Vetores de Suporte 3.0 Treinando nossos classificadores 4.0 Classificando um Dataset 5.0 Comparação: Naive-Bayes VS SVC 6.0 Possíveis melhorias ao modelo<jupyter_code>import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
import sys
import re
import pprint
import subprocess
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction import DictVectorizer
import spotipy 
from spotipy.oauth2 import SpotifyClientCredentials
from sklearn.svm import SVC
from tmm_functions import *<jupyter_output><empty_output><jupyter_text>Utilização da API e da biblioteca SpotipyAo linkar a API a um Client_User e um User_Secret, que são distribuidos pelo Spotify para quem quer fazer uso da API, podemos baixar uma playlist a partir de seu playlist_id e seu user_id, ambos coletados a partir de uma url. Como exemplo de seu funcionamento, vamos baixar duas playlists de Rock e ver como elas são retornadas pelo Spotipy.<jupyter_code>lista_de_urls = ["https://open.spotify.com/user/spotify/playlist/37i9dQZF1DX153gOfbCM2i",
                "https://open.spotify.com/user/spotify/playlist/37i9dQZF1DX49jUV2NfGku"]



def lister(listaurl): #Função que recebe a lista de urls e devolve elas em uma lista de listas de
    liste = []        #["nome","user_id","playlist_id"]
    
    for i in range(len(listaurl)):
        a = re.split(r"/", listaurl[i])
        temp = [a[5]+str(i+1),a[4],a[6]]
        liste.append(temp)
    return liste



lista_pronta = lister(lista_de_urls)
data = ["f2cab99298a34af7a8ae659ef19ca789","5ccf48c89c234bcab96ca6b6f6768a54"]

client=User(data) #Pegando os dados de um arquivo .txt que está escondido com Gitignore


def list_download(list_urls,lista_generos,genre,datavalue): #Função que baixa a playlist usando Spotipy em Dataframe
    
    #Note que já definiremos o gênero musical, já com classificação de Sim(1) ou Não(0)
    
    #list_urls = lista de urls
    #lista_generos = lista de generos - Facilita para ja marcar outros generos como Não(0)
    #genre = genero da playlist
    #datavalue = Se é ou não desse genero - Sim(1) ou Não(0)
    
    df_baixada = client.playlist_downloader(list_urls[0][0],list_urls[0][1],list_urls[0][2])
    print(1)
    df_list = []
    for i in range(1,len(list_urls)):
        df =client.playlist_downloader(list_urls[i][0],list_urls[i][1],list_urls[i][2])
        df_baixada = pd.concat([df_baixada,df])
        print(i+1)
    for i in range(len(lista_generos)):
        df_baixada[lista_generos[i]] = 0
    if datavalue == 1:
        df_baixada[genre] = datavalue
    print("SO DONE")
    return df_baixada #Playlist retornada em Dataframe

lista_generos=['funk','rock','eletronica','metal','sertanejo','rap']

df_spotipy_test = list_download(lista_pronta,lista_generos,"rock",1) #Todos os valores "Rock" serão fornecidos como 1
df_spotipy_test.head()<jupyter_output>1
2
SO DONE<jupyter_text>Perceba que as últimas colunas são os gêneros musicais. Na lógica utilizada no trabalho, __uma música comtempla apenas um estilo musical__, sendo isso uma limitação do nosso modelo, uma vez que sabemos que existem músicas que se enquadram em 2 ou mais estilos.  Entendendo nosso classificadores ClassificadoresClassificadores são ferramentas que quando treinadas conseguem tentar adivinhar qual será a resposta (classificação) de um determinado conjunto de características. Isso quer dizer que você os treina fornecendo certas características e lhe dizendo a resposta desejada, de forma que você tentará depois utilizar esse classificador para adivinhar a resposta de um novo conjunto de dados. Um exemplo bem vísivel seria o seguinte: Imagine que eu quero treinar um computador para indentificar fotos de gatos. Eu lhe mostro algumas fotos de gatos e digo "isso é um gato", depois mostro fotos de coisas que não são gatos, como cachorros, cavalos ou outras coisas e lhe digo "isso não é um gato", com base no input (a foto) e o output (a resposta), ele é treinado para quando fornecida uma foto tentar adivinhar se aquilo é um gato ou não. Classificadores mais complexos já conseguem receber respostas mais complicadas (por ex: gato,cachorro,cavalo,lebre,etc) ao contrário simples booleanos (por ex: não gato, gato) com isso, tornando o Machine Learning mais complexo e eficiente. No nosso caso vamos usar booleanos, pois cumprem muito bem o nosso propósito. Naive BayesO classificador de Naive-Bayes calcula duas probabilidades, uma é a probabilidade do input ser Sim(1) e a outra de ser Não(0). Ele então compara as duas e a maior é considerada a classificação real. O cálculo observa os termos(como tempo, valence, acousticness) como independentes. A conta de cada probabilidade pode ser mostrada pelo exemplo abaixo:Sendo A um objeto com 3 termos: A1, A2, A3.P(Sim/A) = P(A1/Sim)xP(A2/Sim)xP(A3/Sim)XP(Sim)                            P(A)                            Note que P(An/Sim) pode ser definido por { CountAn / TotalSim }, ou seja, quantas vezes esse valores do termo A1 apareceu no treino em Sim. Fora isso, como haverá uma Comparação entre P(Sim/A) e P(Não/A), não precisamos calcular o P(A), pois será igual aos dois e o que import é qual é maior.Dessa forma, se P(Sim/A) > P(Não/A), A = 1, se <, A = 0 Support Vector ClassificatorSupport Vector Machines são poderosos algoritmos para tanto regressão quanto classificação. No caso do classificador(SVC), usamos o que é chamado de classificação discriminativa, ou seja, ao invés de modelar cada classe(como no NB) o SVC visualiza um plano cartesiano e traça uma linha ou curva que consegue separar os dados, da seguinte maneira:Olhando de forma gráfica, vemos que queremos criar uma lógica que consiga dividir quaisquer valores que forem adicionados em 1 ou 0. Observando um plano simples(2D), com os termos A1 e A2 nos eixos, podemos observar que SVC é uma forma de classificar: A função do SVC é dividir esse gráfico em duas partes, por meio de uma reta ou curva:Tudo que estiver acima da linha verde será classificado como 0 e a abaixo como 1.Porém, existem casos onde uma linha não cumprirá sua função, e por isso o SVC consegue utilizar de curvas também:O SVC consegue fazer isso para diversos resultados também:O classificador vetorial trabalha com diversos termos, não apenas dois, mas por questão de visualização utilizamos apenas 2 nesses exemplos.  Treinando nossos classificadoresAgora que entendemos o funcionamento dessas ferramentas, vamos utilizá-las a partir da biblioteca scikit-learn para classificar nossos dados. As facilidades dessa biblioteca são inumeras, mas uma delas é o fator de podermos usar praticamente o mesmo código para o NB quanto para o SVC, como poderá ser observado no código a seguir. Além disso, não vamos usar as duas playlists coletadas nesse código para o classificador,pois seriam apenas cerca de 120 músicas, tal que isso seria um número pequeno para um treino preciso, então coletamos(vide: DataCollector.ipynb) cerca de 600 músicas(10 playlists) de cada gênero. Então para, por exemplo, Rock, vamos utilizar um rock_df, apanhado de 600 musicas de Rock, como 1 e um not_rock_df, um apanhado de 600 musicas de variados estilos sem Rock, como 0.<jupyter_code>class Dataset: #classe para formatação e analise de datasets
    
    def __init__(self,df2):
        #df será passado como string do diretorio do csv
        if type(df2)==str:
            self.df=pd.read_csv(df2)
            self.df["loudness"]=abs(self.df["loudness"])
            self.dict=self.df.filter(items=['acousticness','danceability','instrumentalness','key','liveness','loudness','mode'
                      ,'speechiness','tempo','time_signature','valence','artist']).to_dict('records')
        else:
            #caso o df seja passado como um dataframe do pandas
            self.df=df2
            self.df["loudness"]=abs(self.df["loudness"])
            self.dict=self.df.filter(items=['acousticness','danceability','instrumentalness','key','liveness','loudness','mode'
                      ,'speechiness','tempo','time_signature','valence','artist']).to_dict('records')
            
        self.ans=self.df[self.df.columns[-1]].tolist()
        self.vec=DictVectorizer()
        self.train_songs=self.vec.fit_transform(self.dict).toarray()

# Abrindo Dataframes De Gênero
funk_df = pd.read_csv("funk_df.csv")
rock_df = pd.read_csv("rock_df.csv")
eletronica_df = pd.read_csv("eletronica_df.csv")
metal_df = pd.read_csv("metal_df.csv")
sertanejo_df = pd.read_csv("sertanejo_df.csv")
rap_df = pd.read_csv("rap_df.csv")

# Abrindo Dataframes De Não Gênero
not_funk_df = pd.read_csv("not_funk_df.csv")
not_rock_df = pd.read_csv("not_rock_df.csv")
not_eletronica_df = pd.read_csv("not_eletronica_df.csv")
not_metal_df = pd.read_csv("not_metal_df.csv")
not_sertanejo_df = pd.read_csv("not_sertanejo_df.csv")
not_rap_df = pd.read_csv("not_rap_df.csv")

# Organizando na Classe Dataset
funk_df = Dataset(funk_df)
rock_df = Dataset(rock_df)
eletronica_df = Dataset(eletronica_df)
metal_df = Dataset(metal_df)
sertanejo_df = Dataset(sertanejo_df)
rap_df = Dataset(rap_df)
not_funk_df = Dataset(not_funk_df)
not_rock_df = Dataset(not_rock_df)
not_eletronica_df = Dataset(not_eletronica_df)
not_metal_df = Dataset(not_metal_df)
not_sertanejo_df = Dataset(not_sertanejo_df)
not_rap_df = Dataset(not_rap_df)


class Trainer(): #classe para facilitar o treinamento com o NB e SVC
    def __init__(self):
        self.data={}
        self.nb={}
        self.svc={}
        self.results_nb={}
        self.results_svc={}
        self.vc={}
        

    def pre_format(self,genre,data,not_data):
        data.df[genre]=1
        not_data.df[genre]=0
        dada_concat=Dataset(pd.concat([data.df,not_data.df]))
        return dada_concat
    
    def train(self,name,dataset,genre):  #Função para treinar
        #name = nome do treinamento(pode ser escolhido qualquer nome)
        #dataset = objeto da classe Dataset que recebera o treino
        #genre = genero a ser treinado
        
        self.vc[name]=DictVectorizer() #Transforma uma lista de valores em vetores
        dataset.train_songs=self.vc[name].fit_transform(dataset.dict).toarray()
        #Usa o fit_transform do scikit-learn para organizar e transformar os dados de treinamento em vetores
        
        nb=MultinomialNB() #Definindo o NaiveBayes
        svc=SVC() #Difinindo o SVC
        
        #O fit recebe Input(características) e Output(1 e 0) em listas da seguinte maneira: nb.fit(Input,Output)
        self.nb[name]=nb.fit(dataset.train_songs,dataset.df[genre].tolist())
        self.svc[name]=svc.fit(dataset.train_songs,dataset.df[genre].tolist())
        return "The new dataset has been trained and saved"
    
    def evaluate(self,name,new_songs):
        #metodo para salvar as musicas que a maquina classificou
        #name = nome do treino que você quer usar
        #new_songs = dataset de musicas sem genero classificado
        
        new_songs.df=new_songs.df.reset_index(drop=True)
        new_songs.train_songs=self.vc[name].transform(new_songs.dict).toarray()

        sim_nb=[] #Lista de Sims(1) dados pelo NaiveBayes
        nao_nb=[] #Lista de Nãos(1) dados pelo NaiveBayes
        
        sim_svc=[] #Lista de Sims(1) dados pelo SVC
        nao_svc=[] #Lista de Nãos(1) dados pelo SVC
        
        nb_res=self.nb[name].predict(new_songs.train_songs)
        svc_res=self.svc[name].predict(new_songs.train_songs)
        
        for i in range(len(nb_res)):
            if nb_res[i] == 0:
                nao_nb.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
            else:
                sim_nb.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
            
            if svc_res[i] == 0:    
                nao_svc.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
            else:
                sim_svc.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
                

        self.results_nb[name]={'sim':sim_nb,'nao':nao_nb}
        self.results_svc[name]={'sim':sim_svc,'nao':nao_svc}
        
        return "The result of the evaluation is now saved"
ash=Trainer() #Definindo o nosso treinador, com um nome apropriado

funk_train_df = pd.concat([funk_df.df,not_funk_df.df]) #juntando os dois Dataframes, note: Dataset.df é um Dataframe
ash.train("Funk",Dataset(funk_train_df),"funk")

rock_train_df = pd.concat([rock_df.df,not_rock_df.df])
ash.train("Rock",Dataset(rock_train_df),"rock")

eletronica_train_df = pd.concat([eletronica_df.df,not_eletronica_df.df])
ash.train("eletronica",Dataset(eletronica_train_df),"eletronica")

metal_train_df = pd.concat([metal_df.df,not_metal_df.df])
ash.train("metal",Dataset(metal_train_df),"metal")

sertanejo_train_df = pd.concat([sertanejo_df.df,not_sertanejo_df.df])
ash.train("sertanejo",Dataset(sertanejo_train_df),"sertanejo")

rap_train_df = pd.concat([rap_df.df,not_rap_df.df])
ash.train("rap",Dataset(rap_train_df),"rap")<jupyter_output><empty_output><jupyter_text>Classificando um DatasetAgora que temos um treinamento para cada gênero, vamos usá-los para classificar um Dataset que saibamos o conteúdo, como as duas playlists de Rock que baixamos no começo desse notebook. Com isso, vamos ver quantas músicas de Rock nosso classificador consegue indentificar nesse Dataset e quantas de Funk ele indentifica. Em teoria, se o classificador está funcionando, o número de música Rock deve ser maior que o de músicas Funk(que inclusive deveria ser 0, porém o modelo provavelmente apresentará falhas e acabará por indentificar algum Funk como Rock).<jupyter_code>#Vamos utilizar a função evaluate, que recebe o genero a ser classificado e o Dataset
    
#Perceba que o nome inserido no Evaluate deve ser o do treino que você quer usar, criado anteriormente

test_rock = Dataset(df_spotipy_test)

ash.evaluate("Rock",test_rock)
#print(ash.results_nb["rock"])
#print(ash.results_svc["rock"])


nb_musicas_rock = len(ash.results_nb['Rock']['sim']) #Vendo os resultados no NaiveBayes
nb_musicas_nrock = len(ash.results_nb['Rock']['nao'])

svc_musicas_rock = len(ash.results_svc['Rock']['sim']) #Vendo os resultados no SVC
svc_musicas_nrock = len(ash.results_svc['Rock']['nao'])

print("NB - Rock :{} Não rock: {}".format(nb_musicas_rock,nb_musicas_nrock))
print("SVC - Rock :{} Não rock: {}".format(svc_musicas_rock,svc_musicas_nrock))
print("Podemos ver q nesse caso, o Naive Bayes se saiu melhor que o SVC, uma vez que marcou mais Rock em um Dataset apenas de Rock. Apesar de existirem diferentes métodos de comparação melhores que esse.")
#Agora vamos ver como eles classificam o mesmo Dataset para o gênero Funk
ash.evaluate("Funk",test_rock)
nb_musicas_funk = len(ash.results_nb['Funk']['sim']) #Vendo os resultados no NaiveBayes
nb_musicas_nfunk = len(ash.results_nb['Funk']['nao'])

svc_musicas_funk = len(ash.results_svc['Funk']['sim']) #Vendo os resultados no SVC
svc_musicas_nfunk = len(ash.results_svc['Funk']['nao'])
print("NB - Funk :{} Não Funk: {}".format(nb_musicas_funk,nb_musicas_nfunk))
print("SVC - Funk :{} Não Funk: {}".format(svc_musicas_funk,svc_musicas_nfunk))
print("Podemos perceber que o classificador marcou consideravelmente menos músicas como Funk do que como Rock, o que mostra que apesar de não muito preciso, ele segue uma lógica que se comprova. Além disso, vimos mais uma vez o NB se saindo melhor que o SVC, ao marcar menos 2 erroneamente.")<jupyter_output>NB - Funk :28 Não Funk: 72
SVC - Funk :31 Não Funk: 69
Podemos perceber que o classificador marcou consideravelmente menos músicas como Funk do que como Rock, o que mostra que apesar de não muito preciso, ele segue uma lógica que se comprova. Além disso, vimos mais uma vez o NB se saindo melhor que o SVC, ao marcar menos 2 erroneamente.<jupyter_text>Naive Bayes Vs SVCAgora que já observamos os dois classificadores, vamos fazer uma comparação entre eles em diferentes cenários, um para cada gênero musical. Dessa forma podemos dizer qual método é melhor para nosso conjunto de dados e para nosso objetivo. Para isso, teremos de redefinir a classe Trainer, chamando ela de Trainer2, pois teremos de adicionar uma nova função.<jupyter_code>#Vamos definir novamente a classe treinador, porém agora com algumas mudanças:

# Função test_this que esta um gênero com base em seu dataset e um dos outros datasets selecionados de outro gênero
# Função evaluate agora também salva um dataset de músicas com 1


class Trainer2():
        def __init__(self):
            self.data={}
            self.nb={}
            self.svc={}
            self.results_nb={}
            self.results_svc={}
            self.df_results_nb = {}
            self.df_results_svc = {}
            self.vc={}
            self.svcscore = {}
            self.nbscore = {}
            
        def pre_format(self,genre,data,not_data):
            data.df[genre]=1
            not_data.df[genre]=0
            dada_concat=Dataset(pd.concat([data.df,not_data.df]))
            return dada_concat
    
        def train(self,name,dataset,genre="ans",threshold=[.5,.5]):
            self.vc[name]=DictVectorizer()
            dataset.train_songs=self.vc[name].fit_transform(dataset.dict).toarray()
            #name=nome da chave do dicionario que sera salvo o treinamento,
            #dataset=objeto da classe Dataset que recebera o treino
            
            nb=MultinomialNB(class_prior=threshold)
            svc=SVC()
            if genre=="ans":
                self.nb[name]=nb.fit(dataset.train_songs,dataset.ans)
                self.svc[name]=svc.fit(dataset.train_songs,dataset.ans)
            else:
                self.nb[name]=nb.fit(dataset.train_songs,dataset.df[genre].tolist())
                self.svc[name]=svc.fit(dataset.train_songs,dataset.df[genre].tolist())
            return "The new dataset was trained and saved"
        
        def evaluate(self,name,new_songs): #metodo para salvar as musicas que a maquina classificou
            #name = nome do treino que você quer usar
            #new_songs = dataset de de musicas sem genero classificado
        
            new_songs.df=new_songs.df.reset_index(drop=True)
            new_songs.train_songs=self.vc[name].transform(new_songs.dict).toarray()
    
            sim_nb=[] #Lista de Sims(1) dados pelo NaiveBayes
            nao_nb=[] #Lista de Nãos(1) dados pelo NaiveBayes

            sim_svc=[] #Lista de Sims(1) dados pelo SVC
            nao_svc=[] #Lista de Nãos(1) dados pelo SVC
            
            nb_res=self.nb[name].predict(new_songs.train_songs)
            svc_res=self.svc[name].predict(new_songs.train_songs)
            framesnb = []
            framessvc = []
            for i in range(len(nb_res)):
                if nb_res[i] == 0:
                    
                    nao_nb.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
                else:
                    sim_nb.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
                    framesnb.append(new_songs.df.iloc[i:i+1])
                if svc_res[i] == 0:
                    
                    nao_svc.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
                else:
                    sim_svc.append(new_songs.df['song_title'][i]+' : '+new_songs.df['artist'][i])
                    framessvc.append(new_songs.df.iloc[i:i+1])
    
            self.results_nb[name]={'sim':sim_nb,'nao':nao_nb}
            self.results_svc[name]={'sim':sim_svc,'nao':nao_svc}
            self.df_results_nb[name] = pd.concat(framesnb)
            self.df_results_svc[name] = pd.concat(framessvc)
            
            return "The result of the evaluation is now saved!"
        def check_score(self,name,new_songs,genre="ans"):
            #metodo para checar a eficacia do machine learning
            new_songs.train_songs=self.vc[name].transform(new_songs.dict).toarray()
            
            self.svcscore[name] = self.svc[name].score(new_songs.train_songs,new_songs.df[genre].tolist())
            #print("This is the SVC score: {}".format(self.svcscore[name]))
            self.nbscore[name] = self.nb[name].score(new_songs.train_songs,new_songs.df[genre].tolist())
            #print("This is the NB score: {}".format(self.nbscore[name]))
            #if self.svcscore[name] > self.nbscore[name]:
                  #print("Para {} o SVC se saiu melhor".format(name))
            #else:
                  #print("Para {} o NB se saiu melhor".format(name))
        def test_this(self,name,genre):
            #name=nome que sera salvo o treinamento 
            #genre=o genero que sera treinado
            
            genre_2=genre
            genre_list=['funk','rock','eletronica','metal','sertanejo','rap']

            genre_name=genre+'_df.csv'
            genre=Dataset(genre_name)
            not_genre_name='not_'+genre_name
            not_genre=Dataset(not_genre_name)
            genre_all=self.pre_format(genre,genre,not_genre)

            self.train(name,genre_all,genre)
            test_name_df='test_'+genre_name
            test_genre_df=Dataset(test_name_df)
            x=[]
            for i in range(len(genre_list)):
                if genre_list[i]!=genre_2:
                    x.append(genre_list[i])
            random_genre=np.random.choice(x)
    
            
            test_not_name_df='test_'+random_genre+'_df.csv'
            test_genre_not_df=Dataset(test_not_name_df)

            test_genre_all=self.pre_format(genre,test_genre_df,test_genre_not_df)

            self.check_score(name,test_genre_all,genre)
            self.evaluate(name,test_genre_all)
            
        def playlist_maker(self,genre,mood):
            genre_dataset =Dataset(pd.concat([pd.read_csv(genre+'_df.csv'),pd.read_csv('not_'+genre+'_df.csv')]))
            self.train(genre,genre_dataset,genre,threshold=[0.8,0.2])
            mega_dataset = Dataset(pd.read_csv("giant_df.csv"))
            self.evaluate(genre,mega_dataset)
            filtered_ds = Dataset(self.df_results_nb[genre])

            mood_dataset = Dataset(pd.concat([pd.read_csv(mood+'_df.csv'),pd.read_csv('not_'+mood+'_df.csv')]))
            self.train(mood,mood_dataset,mood)
            self.evaluate(mood,filtered_ds)
            playlist = self.df_results_nb[mood]

            playlist = playlist.drop_duplicates()
            playlist = playlist.sample(frac=1)



            return playlist<jupyter_output><empty_output><jupyter_text>ResultadosPodemos perceber que o SVC se saiu melhor em alguns gêneros enquanto o Naive Bayes em outros. No geral, podemos percecer uma considerável vantagem do NB no caso do nosso projeto. Isso provavelmenete se deve ao fato do SVC tratar as variáveis como complementares e procura achar dependências entre elas. O Classificador por Vetores de Suporte tende a tratar as variaveis como termos de uma única função, estimando que existe uma relação entre elas. O Naive Bayes sugere que as variáveis são completamente independentes, por isso é dado o nome Naive(ingênuo) à essa classificação de Bayes. Os resultados de campo nos mostram que as variáveis dadas pelo Spotify à suas músicas são, provavelmente, independentes, portanto o NB funciona melhor. Para comprovar essa ideia vamos observar um gráfico comparativo, observando um Check_score de cada gênero(1) com cada outro gênero(0) para poder comparar se, por exemplo, o classificador consegue diferenciar Metal de Rock, ou Rap de Eletrônica.<jupyter_code>#Salvando os Dados para Plot

misty = Trainer2()
lista_nb = []
lista_svc = []
lista_plot_generos  = []

for i in lista_generos: #O teste cria todas a instancias que precisamos para o check
    misty.test_this(i,i)

medias_nb = []
medias_svc = []

for i in lista_generos:
    lista_temp_nb = []
    lista_temp_svc = []
    for j in lista_generos:
        if i != j:
            test_not_df = Dataset('test_'+j+'_df.csv')
            test_yes_df = Dataset('test_'+i+'_df.csv')
            test_genre = misty.pre_format(i,test_yes_df,test_not_df)
            misty.check_score(i,test_genre,i)
            
            lista_plot_generos.append(i)
            lista_nb.append(misty.nbscore[i])
            lista_svc.append(misty.svcscore[i])

print("done")
import plotly
import plotly.plotly as py
import plotly.graph_objs as go

plotly.tools.set_credentials_file(username='arthurquintellamo', api_key='<KEY>')

import numpy as np

trace0 = go.Scatter(
    x = lista_plot_generos,
    y = lista_svc,
    name = 'SVC',
    mode = 'markers',
    marker = dict(
        size = 10,
        color = 'rgb(100, 0, 235)',
        line = dict(
            width = 2,
            color = 'rgb(0, 0, 0)'
        )
    )
)

trace1 = go.Scatter(
    x = lista_plot_generos,
    y = lista_nb,
    name = 'NaiveBayes',
    mode = 'markers',
    marker = dict(
        size = 10,
        color = 'rgb(100, 197, 11)',
        line = dict(
            width = 2,
        )
    )
)

data = [trace0, trace1]

layout = dict(title = 'Desempenho Gênero SVC X Naive Bayes',
              yaxis = dict(zeroline = False),
              xaxis = dict(zeroline = False)
             )

fig = dict(data=data, layout=layout)
py.iplot(fig, filename='Desempenho SVC X Naive Bayes')<jupyter_output><empty_output><jupyter_text>Analisando o gráfico, conseguimos perceber que no geral, o Naive Bayes teve desempenho melhor, com exceção apenas em Eletrônica e Metal. Lembrando mais uma vez que NB trabalha com independência e SVC com dependência, podemos imaginar que no caso do Metal e da Eletrônica, as variáveis apresentam uma relação muito mais forte entre si do que em outros gêneros. Além disso, conseguimos perceber que em todos menos Sertanejo e Rap, é possível perceber que os valores de SVC e NB se encontram relativamente mesclados na região central, ou seja, com uma precisão muito semelhante. Sertanejo e Rap apresentam a maior vantagem para NB, uma vez que todos os valores dele são maiores que do SVC, portanto são gêneros que com certeza devem ser sempre analisados com NB. Fazendo o mesmo gráfico agora para Mood, para podermos ver qual classificador utilizaremos<jupyter_code>lista_moods = ["relax","focus","gym","party"]
lista_nb = []
lista_svc = []
lista_plot_generos  = []

medias_nb = []
medias_svc = []






for i in lista_moods:
    lista_temp_nb = []
    lista_temp_svc = []
    misty.test_this(i,i)
    for j in lista_moods:
        if i != j:
            test_not_df = Dataset('test_'+j+'_df.csv')
            test_yes_df = Dataset('test_'+i+'_df.csv')
            test_genre = misty.pre_format(i,test_yes_df,test_not_df)
            misty.check_score(i,test_genre,i)
            
            lista_plot_generos.append(i)
            lista_nb.append(misty.nbscore[i])
            lista_svc.append(misty.svcscore[i])

print("done")
trace0 = go.Scatter(
    x = lista_plot_generos,
    y = lista_svc,
    name = 'SVC',
    mode = 'markers',
    marker = dict(
        size = 10,
        color = 'rgb(100, 0, 235)',
        line = dict(
            width = 2,
            color = 'rgb(0, 0, 0)'
        )
    )
)

trace1 = go.Scatter(
    x = lista_plot_generos,
    y = lista_nb,
    name = 'NaiveBayes',
    mode = 'markers',
    marker = dict(
        size = 10,
        color = 'rgb(100, 197, 11)',
        line = dict(
            width = 2,
        )
    )
)

data = [trace0, trace1]

layout = dict(title = 'Desempenho Mood SVC X Naive Bayes',
              yaxis = dict(zeroline = False),
              xaxis = dict(zeroline = False)
             )

fig = dict(data=data, layout=layout)
py.iplot(fig, filename='Desempenho SVC X Naive Bayes')<jupyter_output>done<jupyter_text>Podemos perceber que dentro dos Moods, o Relax foi o que apresentou a maior vantagem em usar o NB, sendo que nos outros três a diferença pode ser considerada desprezível, portanto vamos assumir que seria melhor usar o Naive Bayes  Criando uma PlaylistCom a intenção de conseguir montar uma função que recebe um gênero e um "mood" e retorna uma playlist, a função playlist_maker(gênero,mood) vai usar um Dataset de mais de 2300 músicas e fultrar, primeiro o gênero e depois o mood. Como o classificador tem uma precisão de entorno de 65%, seria interessante que conseguissemos minimizar as músicas que fossem classificados como dentro do gênero e não fossem. Para isso vamos utilizar de um treshold, que no caso, vai classificar como 1 apenas as músicas que o classificador tiver mais de 80% de certeza de que é dentro desse gênero, ou seja, algumas músicas ficarão de fora da playlist, porém a quantidade de músicas que não são desse gênero serão minímas. Esse método é interessante pois caso a quantidade de músicas da playlist final seja baixa, isso pode ser resolvido por baixar mais músicas pela API.<jupyter_code>misty.playlist_maker("rock","gym")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09106082490771947, 'fraction_numerical': 0.008698443267533301, 'mean_word_length': 3.4719391416678627, 'pattern_counts': {'":': 1, '<': 33, '<?xml version=': 0, '>': 34, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '184848', 'license': 'MIT', 'n_tokens_mistral': 11042, 'n_tokens_neox': 10857, 'n_words': 3050, 'path': 'Principal.ipynb', 'repo_name': 'juanjorgegarcia/TuneMyMood', 'size': '31181'}