มีข้อบกพร่องในคำตอบของ Jason R ซึ่งถูกกล่าวถึงในบท "Art of Computer Programming" ของ Knuth 2. ปัญหาเกิดขึ้นหากคุณมีค่าเบี่ยงเบนมาตรฐานซึ่งเป็นส่วนเล็ก ๆ ของค่าเฉลี่ย: การคำนวณ E (x ^ 2) - (E (x) ^ 2) ได้รับความทุกข์ทรมานจากความไวที่รุนแรงถึงข้อผิดพลาดในการปัดเศษทศนิยม
คุณสามารถลองด้วยตัวคุณเองในสคริปต์ Python:
ofs = 1e9
A = [ofs+x for x in [1,-1,2,3,0,4.02,5]]
A2 = [x*x for x in A]
(sum(A2)/len(A))-(sum(A)/len(A))**2
ฉันได้รับ -128.0 เป็นคำตอบซึ่งเห็นได้ชัดว่าไม่ถูกต้องในการคำนวณเนื่องจากคณิตศาสตร์ทำนายว่าผลลัพธ์ควรไม่เป็นค่าลบ
Knuth อ้างอิงแนวทาง (ฉันจำชื่อผู้ประดิษฐ์ไม่ได้) สำหรับการคำนวณค่าเฉลี่ยการทำงานและส่วนเบี่ยงเบนมาตรฐานซึ่งมีลักษณะดังนี้:
initialize:
m = 0;
S = 0;
n = 0;
for each incoming sample x:
prev_mean = m;
n = n + 1;
m = m + (x-m)/n;
S = S + (x-m)*(x-prev_mean);
และหลังจากแต่ละขั้นตอนแล้วค่าของm
คือค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานสามารถคำนวณตามsqrt(S/n)
หรือsqrt(S/n-1)
ขึ้นอยู่กับคำจำกัดความที่คุณชื่นชอบของส่วนเบี่ยงเบนมาตรฐาน
สมการที่ฉันเขียนด้านบนนั้นแตกต่างจากที่ Knuth เล็กน้อย แต่มันเทียบเท่ากับการคำนวณ
เมื่อฉันมีเวลาอีกไม่กี่นาทีฉันจะเขียนสูตรสูตรข้างต้นใน Python และแสดงว่าคุณจะได้รับคำตอบที่ไม่จำเป็น (หวังว่าจะใกล้เคียงกับค่าที่ถูกต้อง)
update: นี่มันคือ
test1.py:
import math
def stats(x):
n = 0
S = 0.0
m = 0.0
for x_i in x:
n = n + 1
m_prev = m
m = m + (x_i - m) / n
S = S + (x_i - m) * (x_i - m_prev)
return {'mean': m, 'variance': S/n}
def naive_stats(x):
S1 = sum(x)
n = len(x)
S2 = sum([x_i**2 for x_i in x])
return {'mean': S1/n, 'variance': (S2/n - (S1/n)**2) }
x1 = [1,-1,2,3,0,4.02,5]
x2 = [x+1e9 for x in x1]
print "naive_stats:"
print naive_stats(x1)
print naive_stats(x2)
print "stats:"
print stats(x1)
print stats(x2)
ผล:
naive_stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571427}
{'variance': -128.0, 'mean': 1000000002.0028572}
stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571431}
{'variance': 4.0114775868357446, 'mean': 1000000002.0028571}
คุณจะได้ทราบว่ายังคงมีข้อผิดพลาดบางปัดเศษ แต่มันก็ไม่ได้เลวร้ายในขณะที่naive_stats
เพียง pukes
แก้ไข: เพิ่งสังเกตเห็นความคิดเห็นของเบลิซาเรียสอ้างถึงวิกิพีเดียซึ่งพูดถึงอัลกอริธึมของ Knuth