두 지점 사이의 로그 분포 곡선에 대한 올바른 Algorthm은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/604953

  •  03-07-2019
  •  | 
  •  

문제

Tagcloud 가중치의 로그 분포를 생성하는 적절한 방법에 대한 튜토리얼을 많이 읽었습니다. 그들 대부분은 태그를 단계로 그룹화합니다. 이것은 나에게 다소 어리석은 것처럼 보이므로 읽은 내용을 기반으로 자신의 알고리즘을 개발하여 임계 값과 최대 값 사이의 로그 곡선을 따라 태그 수를 동적으로 분배하도록했습니다. 파이썬에서의 본질은 다음과 같습니다.

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) 사이에 직선이 생성됩니다.

알고리즘은 두 지점 사이의 곡선을 잘 근사화하지만 하나의 단점으로 고통받습니다. Mincount는 특별한 경우이며, 그로그가 0을 생성합니다. 이것은 MinCount의 크기가 Minsize보다 작다는 것을 의미합니다. 이 특별한 경우를 해결하기 위해 숫자를 요리하려고 시도했지만 제대로 얻을 수는 없습니다. 현재 나는 단지 MinCount를 특별한 경우로 취급하고 추가 "or 1"로그 카운트 라인에.

두 지점 사이에 곡선을 그릴 수있는 더 정확한 알고리즘이 있습니까?

3 월 3 일 업데이트: 내가 착각하지 않으면 카운트의 로그를 가져간 다음 선형 방정식에 연결합니다. 즉, 특별한 경우에 대한 설명을 x = 1, y = 0으로 y = lnx로 설명합니다. 이것이 Mincount에서 일어나는 일입니다. 그러나 MinCount는 0이 될 수 없으며 태그는 0 번 사용되지 않았습니다.

코드를 시도하고 자신의 번호를 연결하여 테스트하십시오. Mincount를 특별한 경우로 취급하는 것은 괜찮습니다. 나는이 문제에 대한 실제 해결책이 무엇이든간에 더 쉬울 것이라고 생각합니다. 난 그냥 거기처럼 느껴집니다 ~ 해야 하다 이것에 대한 해결책이되고 누군가가 아마도 해결책을 제시했을 것입니다.

4 월 6 일 업데이트: 간단한 Google 검색은 내가 읽은 많은 튜토리얼을 나타냅니다. 이것 아마도 계단식 태그 구름의 가장 완전한 예일 것입니다.

4 월 28 일 업데이트: antti.huima의 솔루션에 대한 응답 : 그래프가 표시되면 알고리즘이 생성하는 곡선이 두 지점 사이의 선 아래에 있습니다. 나는 주변의 숫자를 저글링하려고 노력했지만 여전히 그 곡선을 다른쪽으로 뒤집을 수있는 방법을 생각해 낼 수는 없습니다. 함수가 지수 대신 어떤 형태의 로그로 변경되면, 내가 필요한 것을 정확하게 수행 할 것이라고 생각합니다. 그 맞습니까? 그렇다면 누구든지 이것을 달성하는 방법을 설명 할 수 있습니까?

도움이 되었습니까?

해결책

Antti.huima의 도움 덕분에 나는 내가하려는 일을 다시 생각했습니다.

문제를 해결하는 그의 방법을 취하면서, 나는 Mincount의 로그가 두 지점 사이의 선형 방정식과 동일하는 방정식을 원합니다.

weight(MIN) = ln(MIN-(MIN-1)) + min_weight
min_weight = ln(1) + min_weight

이것은 좋은 출발점을 제공하지만, 지점을 통과하게해야합니다 (max, max_weight). 상수가 필요합니다.

weight(x) = ln(x-(MIN-1))/K + min_weight

우리가 얻는 K를위한 해결 :

K = ln(MAX-(MIN-1))/(max_weight - min_weight)

따라서이 모든 것을 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)
    constant = log(maxcount - (mincount - 1)) / (maxsize - minsize)
    for c in count:
        size = log(c - (mincount - 1)) / constant + minsize
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist

다른 팁

로그인 수에서 크기로 매핑을 시작하겠습니다. 그것은 당신이 언급 한 선형 매핑입니다.

   size
    |
max |_____
    |   /
    |  /|
    | / |
min |/  |
    |   |
   /|   |
0 /_|___|____
    0   a

여기서 Min과 Max는 Min and 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)

이것은 우리에게 다음과 같은 파이썬을 남깁니다.

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])

최소를 수행하기 전에 카운트 목록에 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

당신이 가진 것은 당신은 최소에서 최대에서 카운트가있는 태그가 있다는 것입니다. 임계 값 문제는 임계 값 미만의 모든 수를 임계 값으로 설정하고 그 이후로 만 최소 및 최대를 취하는 데 해당되므로 여기에서 무시할 수 있습니다.

태그 수를 "가중치"에 매핑하려고하지만 기본적으로 다음을 의미하는 "로그 패션"으로 매핑하려고합니다. 먼저 Max Count Get Max_weight 가중치 (예 : 1.75)의 태그 : :

weight(MAX) = max_weight

둘째, Count Min get 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에서는 지수가 0이고 오른쪽의 멀티 랜드는 1이됩니다.

이제 우리는 무게 (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를 계산할 수있는 공식이 있습니다.

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

그리고 당신은 끝났습니다.

로그 척도에서, 당신은 단지 숫자의 로그를 선형으로 그릴뿐입니다 (즉, 선형으로 플로팅하는 척하지만 숫자의 로그를 먼저 그릴 수 있습니다).

제로 문제는 분석적으로 해결할 수 없습니다. 스케일에 대해 최소 크기의 순서를 선택해야하며, 0에 도달 할 수없는 것에 상관없이 제로 문제를 해결해야합니다. 당신이 0으로 무언가를 플로팅하려면, 당신의 선택은 선택적으로 스케일의 최소 크기를 주거나 생략하는 것입니다.

정확한 답변은 없지만 지수 데이터를 선형화하고 싶다고 생각합니다. 지점을 통과하는 선 방정식을 계산하고 해당 방정식의 양쪽의 로그를 사용하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top