[Q-Bot 아이디어 제안] 명성도를 활용한 PostingRank

in #kr7 years ago (edited)

@skan님이 작성하신 [Q-Bot] 화이트리스트 추천을 마감합니다. / 개선점 의견 받습니다를 보고, 어떻게 하면 포스팅에 적절한 가치를 매길 수 있을지 고민해봤습니다.

사람마다 좋은 글이라 판단하는 기준이 다르기 때문에 수치화하는 것이 부적절할 수 있겠지만, 이왕 보팅 봇을 사용할 것이라면 보팅 비율을 정하기 위한 기준을 만들어 보는 것도 괜찮겠다는 생각이 들었습니다.

제가 생각해 본 알고리즘은 구글의 페이지 랭크 알고리즘에 스팀의 명성도 시스템을 섞어 만든 Posting Rank 입니다.

pr.JPG
참고 : 조성문님의 ‘쉽게 설명한’ 구글의 페이지 랭크 알고리즘

페이지 랭크는 구글 검색 시 상위권에 노출되는 페이지의 랭킹을 정하기 위한 알고리즘 입니다.
PR(A) = (1-d)/N + d (PR(T1)/C(T1) + … + PR(Tn)/C(Tn))

PR = 페이지 랭크
T = 페이지
C(T1) = 페이지 T1이 가지고 있는 링크의 총 개수
d = Damping Factor라는 상수
N = 모든 페이지의 수

스팀잇에서 생각해보면
각각의 페이지는 @yguhan 같은 계정,
링크는 리스팀,
우항에 가중치를 부과하는 페이지 랭크는 계정의 명성도로 치환해 볼 수 있습니다.

PR(A) = (1-d)/N + d (R(A1)/RC(A1) + ... + R(An)/RC(An))

PR = Posting Rank(포스팅 랭크)
A = Account(계정)
RC(A1) = Resteem Count(A1의 리스팀 횟수)
R = Reputation(명성도)
d = Damping Factor라는 상수
N = 모든 계정의 수

1.

리스팀을 인용 링크에 대응해 보았는데, 포스팅에서 보팅 < 댓글 << 리스팀 순으로 받기 어려워지기 때문에 나쁘지 않은 선택이라 생각합니다.

모든 글을 리스팀하는 사람보다 어쩌다 한번 리스팀하는 사람이 리스팀한 포스팅이 더 가치가 있다고 보기에, 분모를 리스팀 횟수로 나누어 줍니다. 하지만 오래 활동한 사람의 총 리스팀 횟수가 무조건 크게 나오기 때문에, 7일간 리스팀한 횟수로 보정해줍니다.

2.

무조건 명성도가 높은 유저일수록 좋은 글을 판별하는 안목이 높을 것이라 말하기는 어렵지만, 오랫동안 스팀잇 커뮤니티에서 활동해온 이들이 더 신뢰가 가는 것도 사실입니다. 부계정을 이용한 리스팀같은 어뷰징을 억제하는 효과도 있고, 유명무실했던 명성도의 가치를 실험해볼 좋은 기회라고 생각합니다.

@nand님이 자세히 설명해주신 [Steem Dictionary] 스팀잇에서 reputation (평판,명성)이란?을 읽어보면 명성도가 로그 스케일로 커진다는 것을 알 수 있습니다. 이미 스팀잇을 사용해 온 많은 분들은 명성도가 오를 수록 +1을 올리기가 점점 더 어려워진다는 것을 느끼셨을 겁니다. 점점 올리기 어려워지는 명성도의 난이도를 반영하기 위해 가중치를 reputation의 제곱으로 보정했습니다.

3.

명성도에 의한 영향력을 0~1사이의 수로 만들기 위해 10000을 나눠줍니다.
ex) 명성도 25 -> 25 * 25 / 10000 = 0.0625, 명성도 70 -> 70 * 70 / 10000 = 0.49

4.

포스팅이 리스팀 된 횟수가 0이여도 최소 2% 보팅을 보장하기 위해, (1-d)/N = 0.02로 고정합니다.

1, 2, 3, 4를 적용해 만든 PR은 다음과 같습니다.
PR(A) = 0.02 + 1/10000 * (R(A1)^2/RC(A1) + ... + R(An)^2/RC(An))

PR = Posting Rank(포스팅 랭크)
A = Account(계정)
RC(A1) = Resteem Count(A1의 7일 간 리스팀 횟수)
R = Reputation(명성도)
0.02 = 최소 보팅 비율(2%)

직접 테스트 해보기

@asbear님의 웹브라우저에서 SteemJS로 간단히 스팀파워 임대하기를 응용하여 웹브라우저에서 SteemJS로 간단하게 포스팅 랭크(PostingRank)를 구해봅시다.

0.

크롬에서 새창을 하나 엽니다.
우클릭, "검사" 클릭.
"Console" 클릭
console.JPG

1.

콘솔창에 SteemJS와 UnderscoreJS를 로딩합니다.
아래 코드를 콘솔창에 복사 붙여넣기 합니다.

document.write('<script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>');
document.write('<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>');

cdn.JPG

2.

PostingRank를 구해보고 싶은 포스팅의 링크를 가져옵니다.
[암호화폐 시장의 마법사들-번외편] @twinbraid, 그가 전하는 예언 매매(https://steemit.com/kr/@yguhan/twinbraid)

포스팅 링크에서 저자 yguhan과 마지막 부분에 있는 twinbraid가 사용할 변수입니다.

var author = 'yguhan';
var permlink = 'twinbraid';

위의 코드를 이전과 같은 방식으로 복사해서 콘솔창에 붙여넣기 합니다.
실험해보고 싶은 포스팅의 링크를 가져와서 author와 permlink 부분에 다른 변수값을 넣어 테스트 해보셔도 좋습니다.

3.

위에서 만들어본 PostingRank를 계산하는 공식을 코드화했습니다.
콘솔에 복붙해서 출력값을 확인해봅시다.

var prPromise = new Promise(function(resolve, reject) {

    steem.api.getRebloggedBy(author, permlink, function(err, result){
        
        if (err) return reject(err);

        // 글 작성자를 제외한 리스팀 유저들의 Array
        var rebloggers = _.without(result, author);
        return resolve(rebloggers);
    });

})
.then(function(rebloggers) {

    return _.reduce(rebloggers, function(prPromise, reblogger) {

        return prPromise.then(function(pr) {

            // 명성도 계산
            var reputationPromise = new Promise(function(resolve, err) {
                steem.api.getAccounts([reblogger], function(err, result) {

                    if (err) return reject(err);

                    var reputation = steem.formatter.reputation(result[0].reputation);
                    return resolve(reputation);
                });

            });

            // RC(Resteem Count) 계산
            var rcPromise = new Promise(function(resolve, reject) {
                steem.api.getState("@" + reblogger, function(err, result) {

                    if (err) return reject(err);

                    contents = result.content
                    var resteemContents = _.pick(contents, function(value, key, object){
                        // 해당 글을 리스팀한 유저의 블로그에서 자신의 글이 아니고, 저자 보상을 받지 않은 포스팅의 개수
                        // 즉, 7일 간 리스팀한 포스팅의 총 개수를 계산   
                        return !new RegExp(reblogger).test(key) && value.author_rewards == 0;
                    });
                    rc = _.keys(resteemContents).length;
                    return resolve(rc);

                });
            });

            // PostingRank값 합산
            return Promise.all([reputationPromise, rcPromise]).then(function(results) {
                
                var [reputation, rc] = results;
                // 리스팀 횟수가 0이면 1로 처리
                rc = rc !== 0? rc : 1; 
                // 명성도에 의한 영향력을 0~1로 만들기 위해 10000를 나눔 
                return pr + reputation*reputation/(10000*rc);

            });

        });
    // 리스팀 횟수가 0일 때 2% 보팅
    }, Promise.resolve(0.02));

})
.then(function(pr) {
    // posting rank 출력
    console.log(pr);
})
.catch(function(err) {
    console.log(err);
});

posting_rank.JPG

최종적으로 0.67이 찍혔습니다.
이 값이 PostingRank 값이며, 알고리즘은 이 포스팅에 대해 67%의 보팅 비율을 제안했습니다.
예시로 사용한 [암호화폐 시장의 마법사들-번외편] @twinbraid, 그가 전하는 예언 매매법은 4일 전 작성한 글로 트렌딩(대세글)에 올랐었고, 8번 리스팀 되었습니다.

PostingRank 값이 1 이상인 경우는 극히 드물고 대부분 트렌딩(대세글)에서 찾아볼 수 있었습니다. 하지만 모든 트렌딩의 글이 높은 PostingRank 값을 의미하지는 않습니다. 유료 보팅 봇을 사용하여 인위적으로 보상을 높인 경우 낮은 PostingRank를 기록했습니다.

일상적인 글을 리스팀하는 경우는 적기 때문에 2% 보팅이 다수를 차지할 것이라 예상하고, 몇몇 리스팀은 많이 되었지만 보상 수준이 낮은 글을 발견하는 데 PostingRank를 활용해보면 괜찮겠다는 생각이 듭니다.


@skan님이 계획중인 화이트 리스트 기반의 Q-Bot 외에도
@clayop님이 진행중인 소모임 태그 지원 봇
@virus707님이 진행중인 짱짱맨 태그 지원 봇
들이 무료로 KR 커뮤니티에서 활동하고 있습니다.

PostingRank는 하나의 아이디어일 뿐이고, 봇 운영에 도움이 된다면 좋겠네요.

SteemJS document가 불친절해서 고생했는데 @asbear님과 @morning님이 이전에 올려주신 SteemJS 관련 포스팅을 보고 많은 도움을 받았습니다.
두 분께 감사드립니다 :)

Sort:  

인터뷰 글만 보고 이런 대단한 로직을 겸한 개발자이신 줄은 몰랐네요^^

좋은 아이디어 감사하고, 일단 재밌어서 돌려봤어요^^.
리스팀이 1개라도 있는, 한 달 이내의 제 글 로요. 리스팀이 많은 글은 계산 시간도 꽤 걸리네요.

999.png

9998.png

9799.png

통계를 내지 않아 모르겠는데 직관적으로 느낀 것 몇 가지 적으면,

정보성 글이 리스팀되는 경향이 만약 더 강하다면 정보성 글이 좀 더 우대될 가능성이 있을 것 같고(제 글 중에 40리스팀 글은 뉴비용 사이트 정보글이었거든요. 5.79가 나와서 실제 보상이었던 24$ 대비 PostingRank로는 훨씬 좋았을 것 같아요^^)

이런 경우 리스팀이 많이 되었을 때 약간 몰아주기 특성?이 나올거 같은 느낌이 살짝 있는건 아닌지 생각이 드네요. 스팀에선 저자보상은 선형으로 바뀐 것으로 알거든요.

9996.png

요 그림처럼 말이죠. 물론 다른 글들은 리스팀 수 등에 따라 0.05~0.32까지 적절한 수준으로 나온 것 같아요.

님이 글에서 언급하신 글의 경우 0.67이라 하셨는데 8리스팀된 것과 엄청난 인기글이었음을 섞어 고려하면 적절한 느낌이면서도 좀 아쉽게 느껴지는 부분입니다.

작가에세이/투자에세이는 최고 인기글 제외하고는 리스팀 경향이 적다고 한다면 약간 불리하게 작용할 것 같습니다. 물론 그런 분들이야 매일 트렌딩도 잘 가고 하시니 사실 뭐 보상 측면에서는 충분히 상쇄될 것 같고,

저평가된 글들에 보팅을 강화한다는 아이디어 취지에는 어쩌면 더 부합하는 건지도 모르겠네요.

재미있고 훌륭한 아이디어와 코딩까지 감사합니다. 덕분에 새로운 걸 경험해 보았네요.

개발한 것으로 통계를 내주시고 결과 값까지 분석해서 알려주시다니 정말 감사하네요 !!

페이스북 등에서도 마케팅용 포스팅으로 취업 자소서 목록, 신입생 꿀팁 자료 모음처럼 알짜 정보 공유를 통한 바이럴이 마케팅을 유도하는 경우가 있습니다.
스팀할 때 매우 유용한 사이트들 총정리 ( Useful sites for steemit)는 직접 봐보니 저라도 블로그에 기록해서 남겨두고 싶은 자료이네요. 리스팀도 40번이나 되었으니 그만큼 필요로 하는 뉴비분들이 많았다고 생각합니다. 글의 분량 등에 상관없이 많은 도움을 주었기에 높은 보상을 받아도 전혀 이상하지 않았다고 봅니다.

리스팀을 소비하는 유저층에 따른 구분도 생각해봐야 할 것 같습니다.
많은 글을 매번 리스팀하는 경우, 리스팀 횟수에 반비례하여 그 영향력이 감소합니다. 작가에세이/투자에세이를 소비하는 독자층은 어떤 경향을 띄는지 아직 모르지만, 가끔 한 번씩 리스팀 하여 블로그에 남기기를 희망한다면 리스팀 횟수가 적게 나와도 Posting Rank에 큰 영향도를 끼칠 수 있게 됩니다.

위의 그래프 같은 모습으로 수치가 분포한다면 나름 쓸만하지 않을까 생각되네요.
감사드립니다!!

헛. 새벽에 비몽사몽 써서 좀 길어 줄였는데, 기억나는 대로 다시 남겨놓았어요. 좋게 봐주셔서 감사합니다. 님이 인터뷰하신 글 확인해보면 55리스팀도 있던데 그런 글들에 비하면 너무 허접한 거라서요.뭐 대신 글보상액으로 많이 받으셨으니까 상쇄가 되려나요 ㅎ. 어찌보면 에세이글보다 정보성 글이 더 효용있는 측면도 있긴 하니까 가치판단은 어렵네요.

이게 절대적인 기준이 아니니 수치는 높은데 보상은 낮다거나, 수치는 낮은데 보상은 높은 경우만 주의 깊게 보아도 괜찮지 않을까 싶습니다.
남은 일과도 잘 마무리 하시기 바랍니다 ~

우왕~~~
읽어 봐도 뭐가 뭔지는 모르겠네요. ^^

그래도 한클릭한클릭 따라해서 0.02의 최종값을 얻어냈습니다.^^;;

리스팀이 되려면 유익하고, 정보력이 있는 글을 써야 하는데..
능력이 아쉽네요. ^^

사용해보셨군요!!
잘 돌아갔다니 다행입니다 ㅋㅋ
리스팀 되지 않은 글은 0.02가 나오게 됩니다.

좋은 아이디어입니다!

글을 쓴 저자에 의해 가치가 판단되지 않는게 좋은 아이디어 같습니다.

  1. 명성이 높은 사람이 리스팀 한 글은 좋은 글이다.
  2. 리스팀을 자주 안하는 사람이 리스팀 한 글은 좋은 글이다.

더 좋은 휴리스틱이 있을까 곰곰히 생각해 보았는데, 위 2가지로도 충분할 듯 합니다.
한번 페이아웃된 글을 모아서 랭크를 매겨보고 싶네요. ^^ 왜냐하면 만약 리스팀 행위가 특정 주제의 글에 집중된다면 이를 보정할 방법이 필요할 것 같기 때문입니다.

어떤 글을 사람들이 리스팀하는 지 저도 궁금하네요. 통계내서 봐보는 것도 재밌을 것 같습니다.
첫번 째로 걱정되는 부분은 이벤트 글처럼 리스팀을 요구하는 경우였는 데, skan님이 event 위주의 글을 올리는 사람들은 whitelist에서 배제한다 하였으므로 자연스럽게 해결될 수 있을 것 같습니다.

신기하네요. 스팀잇은 회사직원들이 아니라 이용자들이 꾸려가는 이런 부분들이 넘 신기한거같아요.

스팀을 보면 사용자들이 더 열성적인 것 같습니다.

구글의 시작이 아직까지도 이렇게 응용해서 써먹네요. 검색말고는 잘 못쓸 줄 알았는데....

사실 조금 씩 고쳐서 발전시키는 방향이 괜찮아서 옛것을 많이 참고 하고 있습니다 ...

이런 게 전문가의 손길인가요. 봐도 무슨 말인지 잘 모르겠지만, 스티밋의 발전을 위한 기술이라는 생각은 확실히 듭니다. 시행착오를 거쳐 최적의 알고리즘을 찾아낼 수 있길 바랍니다.^^

감사합니다.
아마 더 뛰어나신 분들이 개선 방향을 제시해 줄 것이라 생각합니다.

구글 페이지 랭크를 떠올리시고 가중치를 알맞게 적용해서 코드까지 만들어주시다니 진심 대단하십니다. 엄청나게 생각할 거리를 주는 글이네요. 제가 너무 좋아하는 조성문님 글도 언급하셔서 깜놀+반가운마음 입니다.
배울수 있는 대목이 많은 좋은 글 좋은 코드 공유 감사드립니다.

감사합니다.
세계님께 칭찬을 들으니 더 기쁘네요.
조성문님의 블로그는 굳이 방문하려 노력하지 않아도 검색 시 상위에 올라와서 자연스럽게 찾아가게 됩니다 :)

저보다 실력이 훨씬 좋으신데 겸손의 말씀이십니다. 제가 특히 비동기 프로그래밍에 매우 취약한데 Promise 사용하신거 보고 멋져부러서 바로 공식 사이트(https://www.promisejs.org) 가서 열공중입니다. 근데 Promise는 기능 자체도 대단하지만 설명도 진짜 깔끔하게 잘해놨네요. @yguhan 님의 깔끔한 코드 덕분에 많이 배웠습니다. 한 번 쓰윽 지나가며 잠깐 보기 너무 아까운 글이라 리스팀 했습니다. 다시 한 번 감사드립니다 :)

조성문님은 말씀을 들어보니 정말 그러네요. 한국어로 개발 관련 글을 구글링 한다면 상위에 항상 나오시는 분 ㅎㅎㅎ

비동기 쪽이 어려우면서도 몇 번 써보면 재미를 느낄 수 있는 것 같습니다.
저도 모르는 게 많아서 매번 참고하면서 배워갑니다.

암호화폐 고수 개발자시군요

납득할 수 있는 보상을 받아가기를
바래보고 싶네요..

이런 과정을 통해서
조금이라도 많은 이들이 사각지대에 놓이지 않았으면 합니다.
잘 보고 가요

사람 수가 증가된 상태에서 스팀은 어떻게 큐레이션의 문제를 해결할지 걱정이 되기도 하네요.
점차 개선되겠죠 ...?

이런 게 필요하지 않은 가 생각해 보고 있었는데 이미 만드셨군요.^^ 감사합니다.~

Coin Marketplace

STEEM 0.23
TRX 0.28
JST 0.042
BTC 104956.85
ETH 3880.98
SBD 3.32