我一直在阅读+研究算法和公式,为我的用户提交的内容计算得分,以显示列表中较高的当前热门/趋势项目,但我承认我在这里有点过头了。
我将介绍一下我在追求的内容......用户将音频上传到我的网站,音频有几个动作:
理想情况下,我想要一种算法,我可以在每次记录(播放,下载等)新活动时更新音频分数,同时下载操作比播放更有价值,比下载更多最喜欢的不是。
如果可能的话,我希望1周以上的音频从列表中大幅下降,以便为更新的内容提供更多的趋势。
我读过有关reddits算法看起来不错的信息,但我对如何调整它以利用我的多个变量以及在大约7天后删除旧文章感到满意。
我们感兴趣的一些文章:
感谢任何帮助!
保
答案 0 :(得分:54)
基本上你可以使用Reddit的公式。由于您的系统仅支持upvotes,您可以对它们进行加权,结果如下:
def hotness(track)
s = track.playedCount
s = s + 2*track.downloadCount
s = s + 3*track.likeCount
s = s + 4*track.favCount
baseScore = log(max(s,1))
timeDiff = (now - track.uploaded).toWeeks
if(timeDiff > 1)
x = timeDiff - 1
baseScore = baseScore * exp(-8*x*x)
return baseScore
因素exp(-8*x*x)
会为您提供理想的下线:
你可以使用任何比你的分数上升更快的功能。由于我们在分数上使用log
,因此即使线性函数也会成倍增加(只要您的分数没有呈指数级增长)。
所以你需要的只是一个函数,只要你不想修改得分就会返回1
,之后会丢弃。我们上面的例子形成了这个功能:
multiplier(x) = x > 1 ? exp(-8*x*x) : 1
让我们说,给定音轨在给定时间播放的概率为50%,下载10%,如1%,喜欢0.1%。然后,以下C ++程序将为您的分数行为提供估计值:
#include <iostream>
#include <fstream>
#include <random>
#include <ctime>
#include <cmath>
struct track{
track() : uploadTime(0),playCount(0),downCount(0),likeCount(0),faveCount(0){}
std::time_t uploadTime;
unsigned int playCount;
unsigned int downCount;
unsigned int likeCount;
unsigned int faveCount;
void addPlay(unsigned int n = 1){ playCount += n;}
void addDown(unsigned int n = 1){ downCount += n;}
void addLike(unsigned int n = 1){ likeCount += n;}
void addFave(unsigned int n = 1){ faveCount += n;}
unsigned int baseScore(){
return playCount +
2 * downCount +
3 * likeCount +
4 * faveCount;
}
};
int main(){
track test;
const unsigned int dayLength = 24 * 3600;
const unsigned int weekLength = dayLength * 7;
std::mt19937 gen(std::time(0));
std::bernoulli_distribution playProb(0.5);
std::bernoulli_distribution downProb(0.1);
std::bernoulli_distribution likeProb(0.01);
std::bernoulli_distribution faveProb(0.001);
std::ofstream fakeRecord("fakeRecord.dat");
std::ofstream fakeRecordDecay("fakeRecordDecay.dat");
for(unsigned int i = 0; i < weekLength * 3; i += 3600){
test.addPlay(playProb(gen));
test.addDown(downProb(gen));
test.addLike(likeProb(gen));
test.addFave(faveProb(gen));
double baseScore = std::log(std::max<unsigned int>(1,test.baseScore()));
double timePoint = static_cast<double>(i)/weekLength;
fakeRecord << timePoint << " " << baseScore << std::endl;
if(timePoint > 1){
double x = timePoint - 1;
fakeRecordDecay << timePoint << " " << (baseScore * std::exp(-8*x*x)) << std::endl;
}
else
fakeRecordDecay << timePoint << " " << baseScore << std::endl;
}
return 0;
}
结果:
这对您来说应该足够了。