今回はimpressionのテーブルの定義とmain.pyの部分を記事にします
シェルスクリプトで関数を実行するために以下の記事を参考にしました
main.pyの中身はこうなっています
main.py
import argparse
import norm
#距離計算
# python main.py music_impression -i '{印象語}'
def music_impression(name):
norm.distance(name)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('function_name',
type=str,
help='set fuction name in this file')
parser.add_argument('-i', '--func_args',
nargs='*',
help='args in function',
default=[])
args = parser.parse_args()
# このファイル内の関数を取得
func_dict = {k: v for k, v in locals().items() if callable(v)}
# 引数のうち,数値として解釈できる要素はfloatにcastする
func_args = [float(x) if x.isnumeric() else x for x in args.func_args]
# 関数実行
ret = func_dict[args.function_name](*func_args)
今回中にあるのはnorm.py(距離計算)だけです
実行環境
macOS Catlina 10.15.7
Python 3.7.5
impressionテーブル
main.pyはimpressionテーブル(以下impression)とmusicテーブル(以下music)の距離計算で上位10曲を表示するというものになっています
musicはSpotify APIを用いているのでimpressionの正確さが結果の正確さに直結します
ここに客観性かつ正確性を持たせるために現在思案中です
とりあえずは25人にそれぞれの印象に当てはまる曲を挙げてもらい、平均を出しました
fc=# select * from impression;
word | danceability | acousticness | energy | liveness | loudness | speechiness | tempo | valence
---------+--------------+--------------+----------+----------+-----------+-------------+------------+----------
excited | 0.559412 | 0.238991 | 0.753471 | 0.177212 | -6.361706 | 0.1073 | 128.399882 | 0.565765
cool | 0.533333 | 0.176618 | 0.796208 | 0.214154 | -5.769667 | 0.0718 | 124.457208 | 0.456937
relax | 0.5335 | 0.420415 | 0.604963 | 0.161387 | -7.346125 | 0.069258 | 121.235208 | 0.504838
sad | 0.509 | 0.403961 | 0.593177 | 0.183709 | -6.792652 | 0.046196 | 119.219565 | 0.408422
fierce | 0.53716 | 0.136491 | 0.823628 | 0.1822 | -5.7808 | 0.099324 | 132.39152 | 0.505112
距離計算
norm.py
import psycopg2
def distance(name):
conn = psycopg2.connect("host=" + "localhost" +
" dbname=" + {データベース名} +
" user=" + {自分のmacのユーザーネーム} +
" password=" + "")
cur = conn.cursor()
cur.execute("SELECT * FROM music")
m = cur.fetchall()
conn.commit()
print("The number of music is ", len(m))
conn.commit()
cur.execute("SELECT music.name, music.artist, distance(music.danceability, music.acousticness, music.energy, music.liveness, music.loudness, music.speechiness, music.tempo, music.valence, impression.danceability, impression.acousticness, impression.energy, impression.liveness, impression.loudness, impression.speechiness, impression.tempo, impression.valence) AS score FROM music, impression WHERE impression.word = '{}' ORDER BY score ASC FETCH FIRST 10 ROWS ONLY".format(name))
n = cur.fetchall()
conn.commit()
print()
print(name)
for n_ in n:
print(n_)
print()
cur.close()
conn.close()
return
distanceという関数をsqlで定義しています
これは距離計算をする関数です
norm.sql
CREATE FUNCTION distance(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float) RETURNS float
AS 'SELECT sqrt(($1 - $9)^2 + ($2 - $10)^2 + ($3 - $11)^2 + ($4 - $12)^2 + ($5 - $13)^2 + ($6 - $14)^2 + ($7 - $15)^2 + ($8 - $16)^2 ) AS distance'
LANGUAGE 'sql';
実行結果(fierce)
こんな感じに結果が出てきます
~/music2imp$ python main.py music_impression -i 'fierce'
The number of music is 2849
fierce
('Fxxker', 'CHANMINA', 0.4662540877118465)
('よー、そこの若いの', 'Takehara Pistol', 0.484637866437422)
('Tik Tik Tok (Rhythm of the Clock) - Original Mix', 'Kid Alina', 0.4947239347393736)
('Dark Horse', 'Katy Perry', 0.6637707380602147)
('ダンシング・ヒーロー(Eat You Up)', 'Yoko Oginome', 0.7221408093890002)
('インフルエンサー 〜off vocal ver.〜 - Off Vocal Version', 'Nogizaka46', 0.7878546612066344)
('pov', 'Ariana Grande', 0.7881882205317551)
('ONLY ONE', 'SPiCYSOL', 0.800737013372686)
('格好悪いふられ方', 'Senri Oe', 0.8075263077974683)
('19 GROWING UP -ode to my buddy-', 'PRINCESS PRINCESS', 0.8426145755830627)