カバーでいくつかの本を判断しましょう


47

誰もがコンテンツが質問をすることを知っています。しかし、良いタイトルも役立ちます。それが最初に目にするものです。その第一印象をプログラムに変え、どのような種類のタイトルがより多くの賛成を得ているかを理解する時です。

これにより、PPCG質問のタイトルを入力として受け取り、そのスコアの予測を返すプログラムまたは関数を作成するように求められます。

たとえばCounting Grains of Rice、入力として受信し、59この場合、スコアに近いものを返そうとする場合があります。非整数の推測は問題-20ありませんが、それ以下の推測は違います。

テストとスコアリング用のデータは次のとおりです。

http://data.stackexchange.com/codegolf/query/244871/names-and-upvotes

スコアリング:プログラムは、このサイトの(PPCG)履歴内のすべての質問で実行され、非公開の質問はカウントされません。関数ln(score + 20)は、各スコアと各推測に適用されます。結果の2つの値セット間の二乗平均平方根誤差がスコアです。低いほど良い。

たとえば、毎回0を推測したプログラムは0.577を獲得し、毎回11を推測したプログラムは0.362を獲得します。

スコアを計算して、回答のタイトルに含めてください。また、この質問がどれだけ多くの賛成票を獲得するかについてのプログラムの予測も含めてください。

制限事項:

  • 過度のハードコーディングを防ぐために、1000文字以下にしてください。

  • 合理的なマシンで1分以内に上記のデータセット全体で実行する必要があります。

  • 標準の抜け穴は閉じられています。


Pythonで書かれたテスターを使用して、あいまいさを解消してください。

import sys
import math
import csv

scores_dict = {}

with open(sys.argv[1], 'r') as csv_file:
    score_reader = csv.reader(csv_file)
    for score, title in score_reader:
        if score == 'Score':
            continue
        scores_dict[title] = int(score)

def rate_guesses(guesser):
    def transform(score):
        return math.log(score + 20) if score > -20 else 0
    off_by_total = 0
    lines_count = 0
    for title in scores_dict:
        guessed_score = guesser(title)
        real_score = scores_dict[title]
        off_by_total += (transform(real_score) - transform(guessed_score)) ** 2
    return (off_by_total/len(scores_dict)) ** .5

def constant11(title):
    return 11

print(rate_guesses(constant11))

19
いい考えですが、データセットが安定していないのは残念なので、しばらくするとスコアが無効になります。また、戦略的な投票の可能性はわずかです。同じ週にこの質問に答え、vox-populiバッジを獲得した人は、疑いを持って閲覧する必要があります。;-)
レベル川セント14

1
タイトルはのようなもの含めたり除外されます[closed][on hold]、該当の?
es1024 14

4
@steveverrillさて、その裏返しは時間の経過とともに、プログラムが過去の投稿だけでなく将来の投稿でもうまくいくかどうかを確認することができます。
isaacg 14

6
ハードコーディングを無効にすることは困難です。ハードコードされた上位投票の質問はそれぞれ、0.4スコアまで減らすことができます。また、あまり一般的なパターンはないようです(笑)。私は、答えは1000バイトで多くのハードコードされた結果をどのように適合させるかだけで競合すると予測しています。
ちょうど半分14

5
テストセットとして質問全体を使用しないでください。ランダムに特定の数(10%〜20%)を事前に選択し、それらをテストセットとして定義する必要があります(ただし、それを誰にも伝えないでください)。過去の履歴を予測するアルゴリズムを作成する方が、将来の予測値を持つアルゴリズム(つまり、特定のサブセットでうまく機能するアルゴリズム)よりもはるかに簡単です。(これらの10%を、私たちが見ることができるものからすべて削除することはさらに良いでしょうが、それは実際にはうまくいきません。)
ジョー

回答:


9

Python 2、991文字、スコア0.221854834221、予測11

import base64
e={}
d=base64.decodestring('vgAcRAEVDAIsqgQYalYaggcjQKwVXAoZWAsYQg0Ckg4VlWEX9hEDRhMe0hckCBkeuhsW3CAWQiEm\nSiMZMiwgTDAZZjIcSLMZfDQDnjwCe2AVaEQCYWEBIEgnDEoXzk0e3lQb5FYVKlkVZlwB+F0XwmI/\nGmRcuGUXWmYdVGkbzmwafG8eaHMdInkggHonRn5sKoMXgIkpbowVOI4cNJAubpQdYpcydJgVypkA\nZpweMp8ZsqEcRKMghKQYkKVPPXEWMqkWHKwbjrEdzLIBNLMf1LQivrYC99UV9rxNRsABNMEiPzob\npc0ActAhn3gcrNUZYNcWYNov/t8VgOEXAuMYqOUWsqUiCPIefPWNbvtKevwWvP0Cl9UsjQMdWwQb\nfQdpJQgWYwkCZRLBjxMWWdkqHRkWNxwB6x8p2SEZyyICSyYcgysaOS0CUy8hezAaGeEVpTRQ3zUz\nZzkZRzohizwwST4c8UAdF0OqG9AXIuEYYRN6208nU1AktVEVJ1IVWeMkIVQXdY4D2VYYD/cYb1om\nG1xA0zoY3uUaRWAhWpBSHWUXQTxGe+cad20CO3AZX3EBw3IiMXcef3gecXsVGXwhw30VbX4W24BD\n6qyQ45YaYYgZ4YobbYwauY4bMY82HZEdO5YmQ5cV35sVxaMbY6gYNas576ws+bADO7QpN7hdLJ8B\n4Eoks8EYX8VU68cYWfcar82QOdAaxdEfQ9UiW/kXL9k2ddwCW90m694enqUCkeEBE+IYWvsfA1FC\nJ+spMVIjhe4WEP0fAfYax/c3MfgbgfkqP/0DLf4V\n')
for i in range(0,600,3):
 e[ord(d[i])*256+ord(d[i+1])]=ord(d[i+2])*2-8
def p(t):
 return e.get(hash(t)%256**2,11)

説明:

これは恥知らずなハードコーディングですが、効率的に実行しようとしています。

前処理:

別のコードで、各タイトルを0〜256 ^ 2-1の値にハッシュしました。これらの値をビンと呼びましょう。各ビンについて、平均スコアを計算しました。(ビンのごく一部で衝突が発生するため、平均が必要です。同じビンに複数のタイトルハッシュがあります。ただし、大多数の場合、各タイトルは独自のビンにマップされます)。

各タイトルの2バイトコードの背後にある考え方は、1バイトでは十分ではないということです-衝突が多すぎるため、各1バイトビンに割り当てるスコアが実際にはわかりません。しかし、2バイトのビンを使用すると、衝突はほとんど発生せず、各タイトルの2バイト表現を効率的に取得できます。

次に、ビンをランク付けします。11を推測するだけでなく、このビンに計算値を割り当てた場合、スコアのゲインを計算します。

エンコード:ビンのキーは2バイトとしてコード化されます。値は1バイトを使用してエンコードされます。-8から300+の間の値を見つけたので、1バイトにするために少し絞らなければなりませんでした:x->(x + 8)/ 2。

実際のコード:

dをバイトトリプレットとして読み取り、上記のエンコードをデコードします。タイトルが与えられたら、そのハッシュ(モジュロ256 ^ 2)を計算し、そのキーが辞書で見つかった場合、マップした値を返します。それ以外の場合は、11を返します。


3
提案:平均スコアはそれほど良くありません。課題のスコアリング機能を見てください、それは非線形です。
デュプリケータ

1
@Deduplicatorありがとう、私は終わった後で気づいた。実は、99%のビンでは衝突が発生していないため、実際には平均はそのビンにマッピングされている単一のタイトルのスコアにすぎません。
Ofri Raviv 14年

16

Javascript ES6

スコア:0.245663
長さ:1000バイト
予測:5

(ダウンボートの予想外の雪崩が原因だと思います。:P)

縮小

E="ABCDEFGHIJKLMNOPQRSTUVWXYZ";E=E+E.toLowerCase()+"0123456789!@#$%;*()";P="RCRHIFMGPGIDQKHMJLLRMLFJGKHEqHPOgJNKGPCHPJNUPOSGJQKKKMELMIJHLKIKNcKDOfSJLFHDILGKIOUKLMLLKMKIHGHJGIIJDGJKIHIIFIGMTIHFJMIKDJGQJKGMKJHPRJPLMGIOPIIIIPBYFMGLEIKIMMRUKFLFGJFKFTHPFODEQTGTHKIJDHNJGDGiHKNYLHHDLJHGILOEViKNEKGQZfHJMIISIJFRHKLJMLPIFJILKKKJKKJESHNLLIKIGKGJJJHKJRGULLSLRONJNEeLKIQGGPQIHPLEIHHIDXjQHNBKOGWWIENRbYoHINHNMKTNKHTGMIPXFJLLMLIHPPLDJJKFUMIQMOKJLJJKIJKNLHRILJIAIbJEZOGIELGHGLOINDPJMJeJWRIIJHSOZDOsOFRRIOIOTIJSGGJKFUIDOINGOcLQEJFEITLMNIIGIGIMG7LPSNLKVOKIFGHJITGOFUJIIRN";K={};"99r1501vz076mip077myv0733it280exx081gt9118i1g279dyx102uho203ejd07433z087uje097kdg1567ft2088rk275dmu1203ez106lih1763ei126f6q101aax084owh088aid161i9y179gvn236ptn3338vf132i55080fke101l4z3789ai281ulm081blm124euz074o5m07513z14117l095qdn092gl30757n5153".replace(/(...)(...)/g,(_,a,b)=>K[a]=1*b);D=40655;N=479;H=(s,T)=>(h=7,[...s].map(c=>h=~~(h*T+c.charCodeAt(0))),h);S=s=>(y=H(s,31),K[((y%D+D)%D).toString(36)]||E.indexOf(P[(H(s,48)%N+N)%N]));

拡大

E = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
E = E + E.toLowerCase() + "0123456789!@#$%;*()";
K = {};
P = "RCRHIFMGPGIDQKHMJLLRMLFJGKHEqHPOgJNKGPCHPJNUPOSGJQKKKMELMIJHLKIKNcKDOfSJL" +
    "FHDILGKIOUKLMLLKMKIHGHJGIIJDGJKIHIIFIGMTIHFJMIKDJGQJKGMKJHPRJPLMGIOPIIIIP" +
    "BYFMGLEIKIMMRUKFLFGJFKFTHPFODEQTGTHKIJDHNJGDGiHKNYLHHDLJHGILOEViKNEKGQZfH" +
    "JMIISIJFRHKLJMLPIFJILKKKJKKJESHNLLIKIGKGJJJHKJRGULLSLRONJNEeLKIQGGPQIHPLE" +
    "IHHIDXjQHNBKOGWWIENRbYoHINHNMKTNKHTGMIPXFJLLMLIHPPLDJJKFUMIQMOKJLJJKIJKNL" +
    "HRILJIAIbJEZOGIELGHGLOINDPJMJeJWRIIJHSOZDOsOFRRIOIOTIJSGGJKFUIDOINGOcLQEJ" +
    "FEITLMNIIGIGIMG7LPSNLKVOKIFGHJITGOFUJIIRN";

   ("99r1501vz076mip077myv0733it280exx081gt9118i1g279dyx102uho203ejd07433z087u" +
    "je097kdg1567ft2088rk275dmu1203ez106lih1763ei126f6q101aax084owh088aid161i9" +
    "y179gvn236ptn3338vf132i55080fke101l4z3789ai281ulm081blm124euz074o5m07513z" +
    "14117l095qdn092gl30757n5153").
        replace( /(...)(...)/g, (_,a,b) => K[a] = 1*b );

D = 40655;
N = 479;
H = (s,T) => (
    h = 7,
    [...s].map( c => h = ~~(h*T + c.charCodeAt(0)) ),
    h
);

S = s => (
    y = H( s, 31 ),
    K[((y%D + D)%D).toString( 36 )] || E.indexOf( P[(H( s, 48 )%N + N)%N] )
);

この関数Sは文字列(タイトル)を受け入れ、そのスコアを返します。

動作に関する注意:

  • ≤70票のタイトルは、> 70票のタイトルとは別に処理されます
  • ≤70票のタイトルは、文字列ハッシュ関数に決して似ていない非常に洗練されたホロノミックキーワードトラッキングの潜在的な最適化アルゴリズムを使用してビンに分類されます。
  • 少し幸せな計算の後、各ビンの最適な推定値は、ビン内のすべてのタイトルの(投票+ 20)の幾何平均から20を引いたものであることがわかります
  • すべての479ビンの最適な推測は、479文字のbase-70文字列としてエンコードされます
  • 70票以上のタイトルについては、他の70票以上のタイトルとの衝突や70票以下のタイトルの誤検出がないことを保証する最先端のハッシュ手法を使用して生成された一意の3桁の36進コードがタイトルに割り当てられます。この最先端の技術は、衝突が発生しなくなるまでランダムなビンカウントを試みることに決して似ていません。
  • 70以上の投票タイトルコードとその投票数は文字列(タイトルごとに6バイト)でエンコードされ、単純なルックアップテーブルに変換されます。したがって、ルーチンには、70を超えるすべての投票タイトルに対してエラーがありません。

10

Python 2、スコア= 0.335027、999文字、この質問の予測11.34828

ボールを転がすだけです。これはどこにも最適ではありません。

派手なSVMのことは、私のランダムなアイデアに過ぎず、実装したいと思ったので、ここにあります。ベースラインが0.02ポイント改善されるため、十分満足しています。しかし、入力のハードコーディングが改善の大部分をもたらす場所であることを示すために、いくつかの答えもハードコーディングしています。

ハードコーディングなしでは、スコアは0.360です(実際、すべての予測は11前後です)

私はscikit-learnnltkを使用しています

import sys
import math
import csv
from sklearn.feature_extraction.text import TfidfVectorizer as TV
from sklearn.svm import SVR
from nltk.stem.porter import PorterStemmer as PS
sd = {}
lr = None
tv = None
with open(sys.argv[1], 'r') as cf:
    sr = csv.reader(cf)
    for sc, t in sr:
        if sc == 'Score':
            continue
        sd[t] = int(sc)
ts,scs = zip(*sd.items())
s = PS()
def analyzer(st):
    r = []
    for word in st.split():
        if word.isdigit():
            r.append('<NUM>')
        elif not word.isalnum():
            r.append('<PUNCT>')
        else:
            r.append(s.stem(word.lower()))
    return r
tv = TV(min_df=25, stop_words='english', analyzer=analyzer)
ti = tv.fit_transform(ts)
lr = SVR()
lr.fit(ti, scs)
d={'4 w':378,'y 42':333,'eeta':280,'an Got':279,'s 2 ':275,"e I'":208,'r CP':203,'? No':179,'B.O':156}
def c(t):
    for s in d.keys():
        if s in t:
            return d[s]
    t = tv.transform([t])
    r = lr.predict(t)[0]+1.5
    return r

わかりません-スコアを外部ファイルから読みますか?それでは、なぜsd [t]を予測しないのでしょうか?これにより、スコア0が得られます...
Ofri Raviv 14

2
それは楽しいではないからです= p
ちょうど半分14

4

Python 2、986文字、スコア0.3480188、予測12

M,S=14.29,23.02
D=lambda x:[ord(y)-32 for y in x]
w='fiLoNoNuMiNoTiMoShOnLoGoLeThRantexgensuBaSqUnInPeReGaMuLinprOuThInThEvEnClOpExPyThADdiSoLiSiMaTrEqUsImAsCoManstARrePoWoReawhapoLandradeTyPaLOsoReCreprediVeReSpebeTiPrImPladaTrihelmakwhicolpaReValpaTrafoROsoumovfinfunpuzyoufaSeQuiwhecoDeChagivcouchehanpoStrdiGraconjavwricalfrowitbinbrafrabuipoi'
for i in range(26):w=w.replace(chr(65+i),chr(97+i)*2)
w=[w[i:i+3]for i in range(0,372,3)]
m=D("(+),+)+=*...+..++'(*)5)/2)*43++16+0,+33*4*/(0.'+>-)+13+(2?8+6;,3;43+4(+.('(,.*.*+56+6)0((++(B,))+E0,-7/)/*++),+***)2+(3(.*)'")
s=D("))'B)'*j+:51(*3+0')+)^'/<-+MG,-1=),-0:A+T&J&K1%,O*()4Y-%:_A.=A*C]MJ-N%)5(%%-0+).*3Q(M&0'%(+$p*)()a8:-T?%5(-*'/.'+)+@,'J&1'&&")
def G(x,m,s):s=s or 1e-9;return(.4/s)*(2.78**(-(x-m)**2./(2*s*s)))
d={w[i]:(m[i],s[i])for i in range(124)}
def Z(t,c):
 p=1
 for W in t.split():
  if len(W)>3:
   W=W[:3].lower()
   if W in d:p*=G(c,*d[W])
 return p*G(c,M,S)
def J(t):return max([(Z(t,r),r)for r in range(-9,99)])[1]

関連する関数はJです。

プログラムは基本的にタイトルの単語を機能として使用する単純ベイズですが、charの制限により非常に制限されています。制限はありますか?まあ...

  • タイトルごとに小文字に変換し、少なくとも4文字の単語のみを調べます。次に、これらの各単語の最初の3文字を特徴として使用します。句読点の削除をスキップして、文字を節約します。
  • 少なくとも19単語の先頭にある文字のトリプレットのみを選択します(これらはw上記に格納されています)。圧縮は、可能な限り多くの二重文字が存在するようにトリプレットを再配置することによって行われ、これらのペアは対応するASCII大文字に置き換えられます(たとえば、fiLoNoN ...→fil、lon、non、...)
  • 各トリプレットについて、表示されるタイトルのスコアを調べて、スコアの平均と標準偏差を計算します。次に、平均/ sdが最大90であるという事実を使用して、それらを整数変換ms上記に格納します(95の印刷可能なASCIIがあるため、直接ASCIIエンコーディングを許可します)
  • G は正規分布関数です-eを2dpに丸め、2 piの逆平方根を1 dpに丸めて文字を節約します。

極端な文字制限により、これは私がこれまでに思いついた最悪のアイデアの1つになりましたが、(うまく機能していなくても)詰め込むことができた量にかなり満足しています。圧縮に関するより良いアイデアがあれば、教えてください:)

(無意味な圧縮を指摘してくれたKennyTMに感謝します)


誤ってコードを実行した場合を除き、圧縮コードは解凍された結果よりもさらに長くなります... w='grge…scse';w=[w[i:i+2]for i in range(0,len(w),2)]165バイトですC=lambda:…;w=C('…')が、179バイトです。
ケニー14

@KennyTMああ-コードをいじくり回していて、圧縮のすべてを追跡できなかった文字制限に合わせようとしていました。:P
Sp3000 14

4

Python 2、535文字、スコア0.330910、11.35の予測

各単語を含むタイトルのスコアを平均し、上位50単語と下位50単語を使用して、guess(title)関数のBASEスコアを変更します。

Pythonコード:

BASE = 11.35
word={}
for sc,ti in csv.reader(open(sys.argv[1])):
    if sc == 'Score': continue
    parts = re.findall(r"[-a-zA-Z']+", ti.lower())
    for p in parts:
        a, c = word.get(p, (0.0,0))
        word[p] = (a+int(sc), c+1)

rank = sorted([(sc/ct,wd) for wd,(sc,ct) in word.items() if ct > 2])
adjust = rank[:50] + rank[-50:]

def guess(title):
    score = BASE
    parts = re.findall(r"[-a-zA-Z']+", title.lower())
    for sc,wd in adjust:
        if wd in parts:
            score *= 0.7 + 0.3*sc/BASE
    return score

3

C

スコア:不明
長さ:5バイト
予測:5

ゴルフ:

int s(char *p){return 5;}

ゴルフをしていない:

int s(char *p)
{
   return 5;
}

スコアのクエリでは、5の平均スコアが得られます。

現時点ではそれをテストする能力がありません。他の人は実行/編集を歓迎します。


さらにガルフド:int s(){return 5;}
ジョシュア

「これにより、PPCG質問のタイトルを入力として受け取り、そのスコアの予測を返すプログラムまたは関数を作成するように求められます。」-申し訳ありませんが、いいえ:0
Joshpbarron 14年

main()を忘れた場合、最初の関数はmain()であるプラットフォームを見ました。たぶん彼はそれに依存しています。
ジョシュア14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.