Hola単語分類コンテスト、または「別のパーセントを取得する場所」

コンテストについての投稿がありましたが、開始から2週間が過ぎました。 しかし、このタスクは非常にエキサイティングなようで、私はこれを間違えず、頭でソリューションに飛び込みました。 この投稿で80 +%ソリューションと私の印象を共有したいと思います。



私の参加はすべて「どこでもう1パーセントを得るのか?」 だから、まず最初に。



私はJSをまったく知らないのでC ++で書き、同僚の助けを借りて完成したソリューションをJSに翻訳しました。



最初に試したのはブルームフィルターです。 辞書の削減:すべての単語を小文字に減らし、で終わるすべての単語をプレフィックスで置き換え、ブルーム用に60 kbのフィルターを割り当てました。 ハッシュ関数として、線形ジェネレーターh [i] = 115249 *(h [i-1] + w [i])+ 33391を選択しました。その結果、精度はそれほど高くなく、約60%でしたが、どこかから始める必要があります。



二番目。 まれな文字の組み合わせによるフィルタリングが追加されました。6つの母音が連続して含まれず、6つの子音が連続して含まれません。 単語が3より長い場合、3つの同一の文字が連続することはありません。



三番目。 長さに応じて単語/ガベージ比を見て、13文字を超えるすべてのテストに結果「ガベージ」を返し始めました。



4番目。 ゴミには引用符付きの単語がさらに含まれています。 新しいルール:引用符を含むすべての「単語ではない」ことを言う( 'をカウントしない)。 その後、精度は約74%の範囲になりました。



5番目。 彼はすべてのバイグラムの確率を数え、めったにバイグラムのない単語をすべて捨て始めました。 彼は辞書からすべての単語のバイグラムの頻度を計算し、この単語またはランダムなバイトシーケンスの確率を考慮し始めました。 バイグラムの確率に基づいて3つの値を使用しました。 積の対数と根の合計。 gnuplotでグラフを作成し、美しい写真ができました。



画像



私が見たチャートには非常に満足していましたが、最終的には、係数を手動で調整した後、わずか76.4%しか得られませんでした。 欠点の中で:マイナス1400バイトのブルーム。



6番目。 彼は文字の頻度をプロットし、同様の方法で製品の合計/対数を取りました。 品質を改善することはできませんでした。バイグラムはすでに良好なろ過を提供しました。



7番目。 ゴミ箱からの単語は不均一に生成され、繰り返しがより一般的であることに気付きました。 上からストップリストを追加しました(20個)。 メモリはブルームフィルターを損なうことになりましたが、合計精度は+ 0.1-0.2%増加しました。 この時点で、ブルームフィルターの可能性はまだ十分に活用されていないと考えました。



第八。 ブルームフィルターには単語を保存せず、3〜6個のプレフィックスのみを保存することにしました。 繰り返しのために非常に小さくなり、ブルームフィルターの精度が大幅に向上しました。 77.8%。 ゴミのストップリストではなく、フィルターに直接保存することができると判断しました。 整数配列を開始し、各単語に1を追加し、繰り返されるごみごとに繰り返しの回数を減らしてから、正の数があるフィルターのビットのみを設定しました。 バイグラムなどの周波数テストに合格しない単語のビットの設定を停止しました。ブルームフィルターの場所は解放されました。 同時に、彼はパラグラフ3から国境を引き上げた。 受け取った合計79%+



第九。 トライグラムを数えようとしました。 メモリを節約するために、5番目の段落と同じ方法で周波数/グラフィックを作成した最初と3番目の文字のみを考慮しました。 精度は0.05%向上しましたが、フィルターサイズをさらに1,500文字減らすと、精度が自然に低下しました。 その結果、彼はこのアイテムを拒否しました。



バイグラムの確率は単語内の位置に依存することに気付きました。 これは、最後の2文字と最初の2文字で最も顕著です。 関連するヒューリスティックを追加しました。 同時に、「単語はQで終わらない」。 しかし、言語学と単語形成の規則(形式、複数形など)から借用したアイデアは、悪化のみをもたらしました。



11番目。 コード内のすべての定数をカスタマイズしました。 何らかの自動化されたツールを作成する方が正しいと思いますが、時間が不足していました。 合計はブルームフィルター502122ビットのサイズを取りました。 8文字の長さのプレフィックスが含まれていました。 しかし、単語の長さでフィルタリング>18。それは80.5 +%でした



12番目。 ランダムではないゴミはスペルミスの単語のように見えます。 したがって、1つのエラーをテストエラーに追加し、それが完全にゴミであるか、単語に似たものであるかどうかを確認するというアイデアが浮上しました。 一連の統計を収集し、一連の実験を実施しましたが、結果はゼロまたは否定的でした。 誰かがそのような小切手を思い浮かべることができましたか?



13番目。 彼は非単語の不均一性に注意を引いた。 頻繁に表示されるか、1回だけ表示されます(妥当なサイズのサンプル)。 彼はすべてのリクエストを保存し始め、150万件後にそれがすでにあるかどうかを確認しましたか? 以前になかった場合、それはゴミを意味します。 前に5つ以上あった場合-また、ゴミ。 まあ、同時に、配列が1,000万ワードごとに切り取られ、メモリが終了しないように一意のワードが削除されました。 100万ごとに合計すると、精度が約1%向上しました。 たとえば、3,500,000語のサンプルでは、​​84%、5,000,000語では85%以上を受け取りました。



このとき、精度が成長の代わりに1〜5%低下し、実際には本当に良いアイデアがなかったことを見て、目が引き締まるたびに終わりました。 13番目のポイントなしで83-85%を獲得することは可能だろうか? 10分の1と100分の1が得られると、これらの数値はますます現実的に見えますが、まだ遠く離れています。 2日目は80%離れています。



最終的な解決策はここにあります: github.com/knst/word-classifier



JSの場合、C ++プログラムを実行した後、データを準備する必要があります。



$ cat bigrams.bin bloom.bin > data && gzip data
      
      






All Articles