5

tagcloud の重みの対数分布を生成する適切な方法についてのチュートリアルをたくさん読みました。それらのほとんどは、タグをステップにグループ化します。これは私にはややばかげているように思えるので、読んだ内容に基づいて独自のアルゴリズムを開発し、しきい値と最大値の間の対数曲線に沿ってタグのカウントを動的に分散させました。これがPythonでの本質です:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, threshold=0, maxsize=1.75, minsize=.75):
    countdist = []
    # mincount is either the threshold or the minimum if it's over the threshold
    mincount = threshold<min(count) and min(count) or threshold
    maxcount = max(count)
    spread = maxcount - mincount
    # the slope of the line (rise over run) between (mincount, minsize) and ( maxcount, maxsize)
    delta = (maxsize - minsize) / float(spread)
    for c in count:
        logcount = log(c - (mincount - 1)) * (spread + 1) / log(spread + 1)
        size = delta * logcount - (delta - minsize)
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist

基本的に、個々のカウントの対数計算がなければ、ポイント (mincount, minsize) と (maxcount, maxsize) の間に直線が生成されます。

このアルゴリズムは 2 点間の曲線を適切に近似しますが、欠点が 1 つあります。mincount は特殊なケースであり、その対数はゼロになります。これは、mincount のサイズが minsize よりも小さくなることを意味します。この特殊なケースを解決するために数字を考えてみましたが、うまくいきません。現在、mincount を特別なケースとして扱い、" or 1" を logcount 行に追加しています。

2 点間に曲線を描くためのより正確なアルゴリズムはありますか?

3 月 3 日更新: 私が間違っていなければ、カウントの対数を取り、それを線形方程式に差し込んでいます。特殊なケースの説明を言い換えると、x=1 で y=lnx では、y=0 です。これが mincount で起こることです。ただし、mincount をゼロにすることはできません。タグは 0 回使用されていません。

コードを試して、独自の番号をプラグインしてテストしてください。最小カウントを特別なケースとして扱うことは私にとっては問題ありません。この問題の実際の解決策よりも簡単だと感じています。これには解決策が必要であり、おそらく誰かが解決策を思いついたように感じます。

4 月 6 日更新: 簡単なGoogle検索で、私が読んだ多くのチュートリアルが見つかりますが、これはおそらく段階的なタグ クラウドの最も完全な例です。

4 月 28 日更新:antti.huima のソリューションへの対応: グラフ化すると、アルゴリズムが作成する曲線は 2 つの点の間の線の下にあります。私は数字を調整しようとしてきましたが、その曲線を線の反対側にひっくり返す方法がまだ思いつかないようです. 関数が指数ではなく何らかの形式の対数に変更された場合、まさに必要なことを行うと思います。あれは正しいですか?もしそうなら、誰でもこれを達成する方法を説明できますか?

4

5 に答える 5

1

あなたが持っているのは、カウントが MIN から MAX までのタグがあるということです。ここでは、しきい値を下回るすべてのカウントをしきい値に設定し、後でのみ最小値と最大値を取得することになるため、しきい値の問題は無視できます。

タグカウントを「重み」にマップしたいが、「対数法」で、これは基本的に(私が理解しているように)次のことを意味します。まず、count MAX のタグは max_weight の重みを取得します (この例では 1.75):

weight(MAX) = max_weight

次に、count MIN のタグは min_weight 重みを取得します (この例では 0.75):

weight(MIN) = min_weight

最後に、カウントが 1 減少すると、重みに定数 K < 1 が乗算され、曲線の急峻さを示します。

weight(x) = weight(x + 1) * K

これを解くと、次のようになります。

weight(x) = weight_max * (K ^ (MAX - x))

x = MAX の場合、指数はゼロで、右側の被乗数は 1 になることに注意してください。

これで、weight(MIN) = min_weight という追加の要件があり、次のように解決できます。

weight_min = weight_max * (K ^ (MAX - MIN))

私たちが得るもの

K ^ (MAX - MIN) = weight_min / weight_max

両辺の対数を取る

(MAX - MIN) ln K = ln weight_min - ln weight_max

すなわち

ln K = (ln weight_min - ln weight_max) / (MAX - MIN)

K < 1 であるため、右辺は必要に応じて負になります。

K = exp((ln weight_min - ln weight_max) / (MAX - MIN))

これで、K を計算する式ができました。この後は、MIN と MAX の間の任意のカウント x を適用するだけです。

weight(x) = max_weight * (K ^ (MAX - x))

これで完了です。

于 2009-03-27T20:19:27.993 に答える
1

ログに記録されたカウントからサイズへのマッピングから始めましょう。それはあなたが言及した線形マッピングです:

   サイズ
    | |
最大 |_____
    | | /
    | | /|
    | | / |
分 |/ |
    | | | |
   /| | |
0 /_|___|____
    0a

ここで、min と max は最小サイズと最大サイズで、a=log(maxcount)-b です。この行は y=mx+c で、x=log(count)-b です。

グラフから、勾配 m が (maxsize-minsize)/a であることがわかります。

y=minsize で x=0 が必要なので、log(mincount)-b=0 -> b=log(mincount)

これにより、次の python が残ります。

mincount = min(count)
maxcount = max(count)
xoffset = log(mincount)
gradient = (maxsize-minsize)/(log(maxcount)-log(mincount))
for c in count:
    x = log(c)-xoffset
    size = gradient * x + minsize

最小カウントが常に少なくとも 1 であることを確認する場合は、最初の行を次のように置き換えます。

mincount = min(count+[1])

min を実行する前に、count リストに 1 を追加します。同じことが、maxcount が常に少なくとも 1 であることを確認する場合にも当てはまります。したがって、上記の最終的なコードは次のようになります。

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, maxsize=1.75, minsize=.75):
    countdist = []
    mincount = min(count+[1])
    maxcount = max(count+[1])
    xoffset = log(mincount)
    gradient = (maxsize-minsize)/(log(maxcount)-log(mincount))
    for c in count:
        x = log(c)-xoffset
        size = gradient * x + minsize
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist
于 2009-03-24T16:01:35.000 に答える
0

正確な答えはわかりませんが、指数データの線形化を調べたいと思います。まず、点を通る直線の方程式を計算し、その方程式の両辺の対数をとります。

于 2009-03-03T03:58:46.427 に答える
0

対数スケールでは、数値の対数を線形にプロットするだけです (つまり、線形にプロットしているふりをして、最初にプロットする数値の対数を取ります)。

ゼロの問題は分析的に解決できません。スケールの最小桁数を選択する必要があり、何があってもゼロに到達することはできません。ゼロで何かをプロットしたい場合、選択肢は任意にスケールの最小桁を与えるか、それを省略することです。

于 2009-03-03T03:15:06.423 に答える