0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

購入したばかりの曲を積極的に再生するための確率設定 -2

Posted at

購入したばかりの曲を積極的に再生するための確率設定 -2

前回の記事
音楽プレイヤーのランダム再生機能を作ることを考え、購入したばかりの曲は再生頻度を高く、購入から日数の経過した曲は再生頻度を下げるといった再生をします、前回の記事では確率設定だけして実際の選曲部分を実装しなかったので今回は選曲部分を実装します

素直に確率を使用してランダムに選曲する場合

確率配列をnまで足し込んだ配列を作成します

    psums = []
    for i, p in enumerate(prob):
        psums.append(np.sum(prob[0:i]))
    psums = np.array(psums)

random.random で 0-1 の乱数を生成し psums の中でそれ以下の配列を検索し、検索結果の最後の要素を選曲対象とします

    for i in range(10):
        r = random.random()
        pidxs = np.where(psums <= r)
        idx = idxs[pidxs[0][-1]]
        print(music_list[idx][0])

pidxs, idxs を使用しインデックスから更にインデックスを参照するという処理がかなり見づらいですね
どこかでまとめてソートし直してしまったほうが楽だったかもしれません

事前にプレイリストを作成しシャッフルする

最低確率の曲を最低1回は再生されるようにしたいので
確率 / 確率の最小値 を切り上げた数字を曲数として設定
各曲をいくつにするかを設定していきます

    pmin = np.min(prob)
    counts = []
    for p in prob:
        counts.append(math.ceil(p / pmin))

設定した数だけ曲を増やしてリスト化、さらにそれらをつなげてリスト化します、プログラムではひとつずつ追加しています

    for i, idx in enumerate(idxs):
        for j in range(counts[i]):
            music_list2.append(music_list[idx][0])
    random.shuffle(music_list2)
    print("\n".join(music_list2[:10]))

i と idx を使い分けているのがプログラムを分かりづらくしていますね…
関数化して頑張ればもっと見やすく作れたような気もします

出力結果

# 素直に確率で10曲選択する
ふざけてないぜ
こんがらがった
北上のススメ
北上のススメ
北上のススメ
君はいなせなガール
君はいなせなガール
北上のススメ
北上のススメ
北上のススメ

# 事前にプレイリストを作成しシャッフル、先頭から10曲を選択する
ふざけてないぜ
bloom
今日はカレーの日
ふざけてないぜ
北上のススメ
君はいなせなガール
北上のススメ
こんがらがった
北上のススメ
北上のススメ

購入から日数経過の短い物が高頻度で出ているのが分かります

ソースコード全体


import matplotlib.pyplot as pyplot
import math
import numpy as np
import random
import sys

def coff_function(x, xmax, ymin):
    y = 1 - x / xmax
    if y < ymin:
        y = ymin
    return y

def test_plot():
    xmax = 1000
    ymin = 1 / xmax
    x = []
    y = []
    for ix in range(xmax + 1000):
        x.append(ix)
        y.append(coff_function(ix, xmax, ymin))
    
    pyplot.plot(x, y)
    pyplot.savefig("test_plot.png")

def test1():
    # 曲名, 購入日からの経過日数
    music_list = [
        ["bloom", 7],
        ["ふざけてないぜ", 1],
        ["優しくなれたなら", 6],
        ["今日はカレーの日", 5],
        ["北上のススメ", 0],
        ["こんがらがった", 6],
        ["君はいなせなガール", 3],
    ]
    
    #music_list = music_list * 10
    
    xmax = len(music_list)
    ymin = 1 / xmax
    names = []
    x = []
    y = []
    for v in music_list:
        ix = v[1]
        names.append(v[0])
        x.append(ix)
        y.append(coff_function(ix, xmax, ymin))
    
    names = np.array(names)
    x = np.array(x)
    y = np.array(y)
    idxs = np.argsort(y)
    idxs = np.flip(idxs) # 確率の高い順番に並べたいので逆転する
    
    names = names[idxs]
    x = x[idxs]
    y = y[idxs]
    
    ysum = np.sum(y)
    prob = y / ysum
    
    #print(names)
    #print(x)
    #print(y)
    #print(prob)
    #print(np.sum(prob))
    
    X = np.c_[names, prob * 100]
    for ix in X:
        print("{}\t{:.2f}%".format(ix[0], float(ix[1])))
    
    # 素直に確率で10曲選択する
    print("# 素直に確率で10曲選択する")
    psums = []
    for i, p in enumerate(prob):
        psums.append(np.sum(prob[0:i]))
    psums = np.array(psums)
    #print(psums)
    
    for i in range(10):
        r = random.random()
        pidxs = np.where(psums <= r)
        idx = idxs[pidxs[0][-1]]
        print(music_list[idx][0])
    
    # 事前にプレイリストを作成しシャッフル、先頭から10曲を選択する
    print()
    print("# 事前にプレイリストを作成しシャッフル、先頭から10曲を選択する")
    pmin = np.min(prob)
    counts = []
    for p in prob:
        counts.append(math.ceil(p / pmin))
    music_list2 = []
    for i, idx in enumerate(idxs):
        for j in range(counts[i]):
            music_list2.append(music_list[idx][0])
    random.shuffle(music_list2)
    print("\n".join(music_list2[:10]))
    

def main():
    #test_plot()
    test1()

if __name__ == "__main__":
    main()

以上です

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?