อ่าน 22 นาที
อัลกอริทึมสำหรับการคำนวณความแปรปรวน
Statistical algorithms/ค่าเบี่ยงเบนทางสถิติและการกระจายตัว/ใช้วันที่ dmy ตั้งแต่เดือนกรกฎาคม 2020
อัลกอริทึมสำหรับการคำนวณความแปรปรวนมีบทบาทสำคัญในสถิติเชิงคำนวณความยากลำบากที่สำคัญในการออกแบบอัลกอริทึม ที่ดี สำหรับปัญหานี้คือ...
อัลกอริทึมสำหรับการคำนวณความแปรปรวน
อัลกอริทึมสำหรับการคำนวณความแปรปรวนมีบทบาทสำคัญในสถิติเชิงคำนวณความยากลำบากที่สำคัญในการออกแบบอัลกอริทึม ที่ดี สำหรับปัญหานี้คือ สูตรสำหรับความแปรปรวนอาจเกี่ยวข้องกับผลรวมของกำลังสอง ซึ่งอาจนำไปสู่ความไม่เสถียรทางตัวเลขรวมถึงการล้นทางคณิตศาสตร์เมื่อจัดการกับค่าขนาดใหญ่
อัลกอริทึมแบบง่าย
สูตรสำหรับการคำนวณความแปรปรวนของประชากร ทั้งหมด ที่มีขนาดNคือ:
เมื่อใช้การแก้ไขของเบสเซลในการคำนวณ ค่าประมาณ ที่ไม่เอนเอียงของความแปรปรวนของประชากรจากตัวอย่างจำกัดจำนวนn ตัวอย่างสูตรคือ:
ดังนั้น อัลกอริทึมแบบง่ายในการคำนวณค่าความแปรปรวนโดยประมาณจึงมีดังต่อไปนี้:
- ให้n ← 0, Sum ← 0, SumSq ← 0
- สำหรับข้อมูลแต่ละค่าx :
- n ← n + 1
- ผลรวม ← ผลรวม + x
- SumSq ← SumSq + x × x
- Var = (SumSq − (ผลรวม × ผลรวม) / n) / (n − 1)
อัลกอริทึมนี้สามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อคำนวณความแปรปรวนของประชากรที่มีจำนวนจำกัด: เพียงแค่หารด้วยnแทนที่จะเป็นn − 1 ในบรรทัดสุดท้าย
เนื่องจากSumSqและ(Sum×Sum)/ nอาจเป็นตัวเลขที่คล้ายคลึงกันมากการตัดทอนอาจทำให้ความแม่นยำของผลลัพธ์น้อยกว่าความแม่นยำโดยธรรมชาติของเลขคณิตจุดลอยตัวที่ใช้ในการคำนวณ ดังนั้นจึงไม่ควรใช้อัลกอริทึมนี้ในทางปฏิบัติ[ 1 ] [ 2 ]และได้มีการเสนออัลกอริทึมทางเลือกอื่น ๆ ที่มีเสถียรภาพทางตัวเลขหลายตัว[ 3 ]ซึ่งเป็นเรื่องที่แย่มากหากค่าเบี่ยงเบนมาตรฐานมีขนาดเล็กเมื่อเทียบกับค่าเฉลี่ย
การคำนวณข้อมูลที่เลื่อนแล้ว
ค่าความแปรปรวนไม่เปลี่ยนแปลงเมื่อพารามิเตอร์ตำแหน่ง เปลี่ยนไป ซึ่งเป็นคุณสมบัติที่สามารถนำมาใช้เพื่อหลีกเลี่ยงการหักล้างกันอย่างรุนแรงในสูตรนี้ได้
โดยมีค่าคงที่ใดๆ ซึ่งนำไปสู่สูตรใหม่
ยิ่งค่าใกล้ค่าเฉลี่ยมากเท่าไหร่ ผลลัพธ์ก็จะยิ่งแม่นยำมากขึ้นเท่านั้น แต่การเลือกค่าภายในช่วงตัวอย่างจะรับประกันความเสถียรที่ต้องการ หากค่ามีขนาดเล็ก ก็จะไม่มีปัญหาเกี่ยวกับผลรวมของกำลังสอง ในทางตรงกันข้าม หากค่ามีขนาดใหญ่ ก็หมายความว่าความแปรปรวนก็มีขนาดใหญ่เช่นกัน ไม่ว่าในกรณีใด พจน์ที่สองในสูตรจะมีค่าน้อยกว่าพจน์แรกเสมอ ดังนั้นจึงไม่มีการหักล้างเกิดขึ้น[ 2 ]
หากนำตัวอย่างแรกมาใช้เพียงอย่างเดียวอัลกอริทึมสามารถเขียนได้ในภาษาโปรแกรม Pythonดังนี้
def shifted_data_variance ( data ): if len ( data ) < 2 : return 0.0 K = data [ 0 ] n = Ex = Ex2 = 0.0 for x in data : n += 1 Ex += x - K Ex2 += ( x - K ) ** 2 variance = ( Ex2 - Ex ** 2 / n ) / ( n - 1 ) # ใช้ n แทน (n-1) ถ้าต้องการคำนวณค่าความแปรปรวนที่แน่นอนของข้อมูลที่กำหนด# ใช้ (n-1) ถ้าข้อมูลเป็นตัวอย่างของประชากรขนาดใหญ่กว่าคืนค่าความแปรปรวนอัลกอริทึมแบบสองรอบ
แนวทางอื่นที่ใช้สูตรคำนวณความแปรปรวนที่แตกต่างออกไป จะคำนวณค่าเฉลี่ยของตัวอย่างก่อน
จากนั้นจึงคำนวณผลรวมของกำลังสองของผลต่างจากค่าเฉลี่ย
โดยที่sคือค่าเบี่ยงเบนมาตรฐาน ซึ่งคำนวณได้จากโค้ดต่อไปนี้:
def two_pass_variance ( data ): n = len ( data ) mean = sum ( data ) / n variance = sum (( x - mean ) ** 2 for x in data ) / ( n - 1 ) return varianceโค้ดส่วนนี้ หากรันบนCPython 3.12 และเวอร์ชันที่ใหม่กว่า จะมีความเสถียรทางตัวเลขเสมอ เนื่องจากเวอร์ชันเหล่านี้ใช้ รูปแบบ การรวมแบบชดเชย ของ Neumaier สำหรับsum()ฟังก์ชัน ทำให้ทนต่อข้อผิดพลาดจากการปัดเศษซ้ำๆ[ 4 ]ภาษาที่เน้นตัวเลขหลายภาษามีโครงสร้างที่คล้ายกัน
หากนำอัลกอริทึมนี้ไปใช้กับการเพิ่มแบบง่ายๆsum = 0; for x in sum += x; mean = sum / nจะทำให้มีเสถียรภาพเชิงตัวเลขเฉพาะเมื่อnมีขนาดเล็กเท่านั้น เนื่องจากการสะสมของข้อผิดพลาดจากการปัดเศษ[ 1 ] [ 5 ]
อัลกอริทึมแบบเพิ่มทีละขั้น
การคำนวณค่าความแปรปรวนในรอบเดียวโดยตรวจสอบแต่ละค่าเพียงครั้งเดียว มักเป็นประโยชน์ เช่น ในกรณีที่เก็บรวบรวมข้อมูลโดยมีพื้นที่จัดเก็บไม่เพียงพอที่จะเก็บค่าทั้งหมด หรือเมื่อต้นทุนในการเข้าถึงหน่วยความจำสูงกว่าต้นทุนในการคำนวณ สำหรับอัลกอริทึมแบบออนไลน์ ดังกล่าว จำเป็นต้องมี ความสัมพันธ์เวียนเกิดระหว่างปริมาณต่างๆ ซึ่งสามารถคำนวณสถิติที่ต้องการได้อย่างเสถียรในเชิงตัวเลข
ข้อมูลที่เลื่อนเพิ่มขึ้น
อัลกอริทึมข้อมูลที่เลื่อนของเราก่อนหน้านี้ประกอบด้วยการอัปเดตข้อมูลอย่างง่ายในลูป ซึ่งเป็นแบบเพิ่มขึ้นตามธรรมชาติ สามารถแสดงได้ดังนี้: [ 2 ]
คลาสShiftDataVariance : def __init__ ( self ): self . K = 0.0 self . n = 0 self . Ex = 0.0 self . Ex2 = 0.0def add_variable ( self , x : float ): if self . n == 0 : self . K = x self . n += 1 self . Ex += x - self . K self . Ex2 += ( x - self . K ) ** 2def remove_variable ( self , x : float ) : self.n - = 1 self.Ex - = x - self.K self.Ex2 - = ( x - self.K ) ** 2def add_variables ( self , xs : list [ float ]): # Python ใช้อัลกอริทึมของ Neumaier สำหรับฟังก์ชัน sum() ในตัว# ซึ่งมีความแม่นยำมากกว่าลูปธรรมดาif self . n == 0 and xs : self . K = xs [ 0 ] self . n += len ( xs ) self . Ex += sum ( x - self . K for x in xs ) self . Ex2 += sum (( x - self . K ) ** 2 for x in xs )def get_mean ( self ) - > float : return self.K + self.Ex / self.ndef get_variance ( self ) - > float : return ( self.Ex2 - self.Ex ** 2 / self.n ) / ( self.n - 1 )อัลกอริทึมออนไลน์ของเวลฟอร์ด
ในทำนองเดียวกันกับอัลกอริธึมแบบสองรอบข้างต้น ยังคงเป็นที่พึงปรารถนาที่จะใช้ค่าเฉลี่ย ที่แท้จริง ของข้อมูลแทนที่จะเลือกเพียงองค์ประกอบแรก สูตรต่อไปนี้สามารถใช้เพื่ออัปเดตค่าเฉลี่ยและค่าความแปรปรวน (โดยประมาณ) ของลำดับสำหรับองค์ประกอบเพิ่มเติมx nโดยที่หมายถึงค่าเฉลี่ยตัวอย่างของตัวอย่าง n ตัวแรก หมายถึงค่าความแปรปรวน ตัวอย่าง แบบมีอคติและหมายถึงค่าความแปรปรวนตัวอย่างแบบไม่มีอคติ
สูตรเหล่านี้มีปัญหาเรื่องความไม่เสถียรทางตัวเลข เนื่องจากมีการลบจำนวนเล็กๆ ออกจากจำนวนมากซึ่งแปรผันตามn ซ้ำๆ ปริมาณที่ดีกว่าสำหรับการปรับปรุงคือผลรวมของกำลังสองของความแตกต่างจากค่าเฉลี่ยปัจจุบันซึ่งในที่นี้ใช้สัญลักษณ์:
อัลกอริทึมต่อไปนี้ถูกค้นพบโดย Welford [ 6 ] [ 7 ]และได้รับการวิเคราะห์อย่างละเอียด[ 2 ] [ 8 ]นอกจากนี้ยังเป็นเรื่องปกติที่จะใช้สัญลักษณ์และ[ 9 ] ตัวอย่างการใช้งาน Python สำหรับอัลกอริทึมของ Welford แสดงไว้ด้านล่าง โดยใช้กรอบงานเดียวกันกับอัลกอริทึม "ข้อมูลที่เลื่อน" ข้างต้น:
คลาสWelfordVariance : def __init__ ( self ): # เปรียบเทียบกับ ShiftDataVariance: self . mean = 0.0 # = K + Ex / n self . count = 0 # = n self . M2 = 0.0 # = Ex2 - (Ex)^2 / ndef add_variable ( self , x : float ): self . count += 1 old_mean = self . mean self . mean += ( x - self . mean ) / self . count self . M2 += ( x - old_mean ) * ( x - self . mean )def remove_variable ( self , x : float ) : self.count - = 1 new_mean = self.mean self.mean - = ( x - self.mean ) / self.count self.M2 - = ( x - new_mean ) * ( x - self.mean )def get_mean ( self ) - > float : return self.meandef get_variance ( self ) - > float : return self.M2 / self.countdef get_sample_variance ( self ) - > float : return self.M2 / ( self.count - 1 )อัลกอริทึมนี้มีโอกาสน้อยที่จะสูญเสียความแม่นยำเนื่องจากการหักล้างที่รุนแรงแต่ก็อาจไม่มีประสิทธิภาพเท่าที่ควรเนื่องจากการดำเนินการหารภายในลูป สำหรับอัลกอริทึมแบบสองขั้นตอนที่แข็งแกร่งเป็นพิเศษสำหรับการคำนวณความแปรปรวน เราสามารถคำนวณและลบค่าประมาณของค่าเฉลี่ยก่อน จากนั้นจึงใช้อัลกอริทึมนี้กับค่าความคลาดเคลื่อน
อัลกอริทึมแบบขนานด้านล่างนี้แสดงให้เห็นถึงวิธีการรวมชุดสถิติหลายชุดที่คำนวณทางออนไลน์เข้าด้วยกัน
อัลกอริทึมแบบเพิ่มน้ำหนัก
อัลกอริทึมสามารถขยายเพื่อจัดการกับน้ำหนักตัวอย่างที่ไม่เท่ากันได้ โดยแทนที่ตัวนับn แบบง่าย ด้วยผลรวมของน้ำหนักที่เห็นจนถึงตอนนี้ เวสต์ (1979) [ 10 ]แนะนำอัลกอริทึมแบบเพิ่มขึ้น นี้ :
จากcollections นำเข้าnamedtuple WeightedVariances = namedtuple ( "WeightedVariances" , "pop freq reli" ) def weighted_incremental_variance ( data_weight_pairs ): w_sum = w_sum2 = mean = S = 0สำหรับx และw ในdata_weight_pairs : w_sum = w_sum + w w_sum2 = w_sum2 + w ** 2 mean_old = mean mean = mean_old + ( w / w_sum ) * ( x - mean_old ) S = S + w * ( x - mean_old ) * ( x - mean )population_variance = S / w_sum # การแก้ไขของ Bessel สำหรับตัวอย่างที่มีการถ่วงน้ำหนัก# น้ำหนักความถี่sample_frequency_variance = S / ( w_sum - 1 )# น้ำหนักความน่าเชื่อถือsample_reliability_variance = S / ( w_sum - w_sum2 / w_sum ) return WeightedVariances ( population_variance , sample_frequency_variance , sample_reliability_variance )อัลกอริทึมแบบขนาน
Chan และคณะ[ 11 ]ตั้งข้อสังเกตว่าอัลกอริทึมออนไลน์ของ Welford ที่ระบุรายละเอียดไว้ข้างต้นเป็นกรณีพิเศษของอัลกอริทึมที่ใช้สำหรับการรวมเซตที่กำหนดและ:
- .
วิธีนี้อาจมีประโยชน์ เช่น ในกรณีที่ต้องกำหนดหน่วยประมวลผลหลายหน่วยให้กับส่วนต่างๆ ของข้อมูลป้อนเข้า
วิธีการประมาณค่าเฉลี่ยของ Chan นั้นไม่เสถียรทางตัวเลขเมื่อและ มีค่ามากทั้งคู่ เนื่องจากข้อผิดพลาดเชิงตัวเลขในไม่ได้ถูกปรับขนาดลงในลักษณะเดียวกับในกรณี ในกรณีเช่นนี้ ควรเลือกใช้โดยการนำคลาสจากข้างต้นมาใช้ซ้ำ เราจะได้: WelfordVariance
def merge ( a : WelfordVariance , b : WelfordVariance ) -> WelfordVariance : ab = WelfordVariance () ab . count = a . count + b . count delta = b . mean - a . mean ab . mean = ( a . count * a . mean + b . count * b . mean ) / ab . count ab . M2 = a . M2 + b . M2 + delta ** 2 * a . count * b . count / ab . count return ab# ตัวอย่าง: ab = merge ( a , b ) print ( ab . get_sample_variance ())อัลกอริทึมนี้อนุญาตให้แบ่งชุดข้อมูลออกเป็นหลายส่วน ประมวลผลแบบขนาน แล้วรวมผลลัพธ์เข้าด้วยกัน ซึ่งช่วยให้สามารถทำการประมวลผลแบบขนานได้ทุกรูปแบบ รวมถึงAVX , GPUและคลัสเตอร์คอมพิวเตอร์อัลกอริทึมนี้ยังสามารถปรับใช้กับสถิติลำดับสูงกว่า รวมถึงความแปรปรวนร่วมได้อีกด้วย[ 3 ] [ 12 ]
ตัวอย่าง
สมมติว่าการคำนวณเลขทศนิยมทั้งหมดใช้ เลขคณิต ความแม่นยำสองเท่ามาตรฐาน IEEE 754พิจารณาตัวอย่าง (4, 7, 13, 16) จากประชากรอนันต์ จากตัวอย่างนี้ ค่าเฉลี่ยของประชากรที่ประมาณได้คือ 10 และค่าประมาณความแปรปรวนของประชากรที่ไม่เอนเอียงคือ 30 ทั้งอัลกอริทึมแบบง่ายและอัลกอริทึมแบบสองรอบคำนวณค่าเหล่านี้ได้อย่างถูกต้อง
ต่อไปให้พิจารณาตัวอย่าง ( 10 8 + 4 , 10 8 + 7 , 10 8 + 13 , 10 8 + 16 ) ซึ่งให้ค่าประมาณความแปรปรวนเดียวกันกับตัวอย่างแรก อัลกอริทึมแบบสองรอบคำนวณค่าประมาณความแปรปรวนนี้ได้อย่างถูกต้อง แต่อัลกอริทึมแบบง่ายจะส่งคืนค่า 29.333333333333332 แทนที่จะเป็น 30
แม้ว่าการสูญเสียความแม่นยำนี้อาจยอมรับได้และมองว่าเป็นข้อบกพร่องเล็กน้อยของอัลกอริทึมแบบง่าย แต่การเพิ่มค่าชดเชยให้มากขึ้นจะทำให้ข้อผิดพลาดร้ายแรงขึ้น ลองพิจารณาตัวอย่าง ( 10⁹ + 4 , 10⁹ + 7 , 10⁹ + 13 , 10⁹ + 16 ) อีกครั้งที่ค่าความแปรปรวนของประชากรที่ประมาณไว้ที่ 30 นั้นคำนวณได้อย่างถูก ต้องโดยอัลกอริทึมแบบสองรอบ แต่ในอัลกอริทึมแบบง่ายกลับคำนวณได้เป็น −170.66666666666666 นี่เป็นปัญหาที่ร้ายแรงของอัลกอริทึมแบบง่าย และเกิดจากการหักล้างกันอย่างรุนแรงในการลบตัวเลขที่เหมือนกันสองตัวในขั้นตอนสุดท้ายของอัลกอริทึม
สถิติลำดับสูง
Terriberry [ 12 ]ขยายสูตรของ Chan เพื่อคำนวณโมเมนต์กลางลำดับ ที่สามและสี่ ซึ่งจำเป็นสำหรับการประเมินค่าความเบี่ยงเบนและความโค้ง เช่น :
ในที่นี้ผลรวมของกำลังของความแตกต่างจากค่าเฉลี่ยคือ...
สำหรับกรณีเพิ่มทีละน้อย (เช่น) จะลดรูปเหลือดังนี้:
ด้วยการคงค่าเดิมไว้จึงจำเป็นต้องใช้การหารเพียงครั้งเดียว และด้วยเหตุนี้จึงสามารถคำนวณ สถิติลำดับสูงกว่า ได้โดยมีต้นทุนเพิ่มขึ้นเพียงเล็กน้อย
ตัวอย่างของอัลกอริธึมออนไลน์สำหรับการคำนวณค่าความโค้ง (kurtosis) ที่นำมาใช้ตามที่อธิบายไว้มีดังนี้:
def online_kurtosis ( data ): n = mean = M2 = M3 = M4 = 0สำหรับx ในdata : n1 = n n = n + 1 delta = x - mean delta_n = delta / n delta_n2 = delta_n ** 2 term1 = delta * delta_n * n1 mean = mean + delta_n M4 = M4 + term1 * delta_n2 * ( n ** 2 - 3 * n + 3 ) + 6 * delta_n2 * M2 - 4 * delta_n * M3 M3 = M3 + term1 * delta_n * ( n - 2 ) - 3 * delta_n * M2 M2 = M2 + term1# หมายเหตุ คุณอาจคำนวณค่าความแปรปรวนโดยใช้ M2 และค่าความเบี่ยงเบนโดยใช้ M3 ก็ได้# ข้อควรระวัง: หากข้อมูลนำเข้าทั้งหมดเหมือนกัน M2 จะเป็น 0 ส่งผลให้มีการหารด้วย 0 kurtosis = ( n * M4 ) / ( M2 ** 2 ) - 3 return kurtosisPébaÿ [ 13 ] ขยายผลลัพธ์เหล่านี้เพิ่มเติมไปยัง โมเมนต์กลาง ลำดับตามอำเภอใจสำหรับกรณีเพิ่มขึ้นและกรณีจับคู่ และต่อมา Pébaÿ et al. [ 14 ] สำหรับโมเมนต์ถ่วงน้ำหนักและโมเมนต์ประกอบ นอกจากนี้ยังสามารถพบสูตรที่คล้ายกันสำหรับ ความแปรปรวนร่วมได้ที่ นั่น
Choi และ Sweetman [ 15 ] เสนอวิธีการทางเลือกสองวิธีในการคำนวณค่าความเบี่ยงเบนและความโค้ง ซึ่งแต่ละวิธีสามารถประหยัด ความต้องการ หน่วยความจำคอมพิวเตอร์และเวลา CPUในบางแอปพลิเคชันได้อย่างมาก วิธีแรกคือการคำนวณโมเมนต์ทางสถิติโดยการแบ่งข้อมูลออกเป็นช่วงๆ แล้วคำนวณโมเมนต์จากรูปทรงเรขาคณิตของฮิสโตแกรม ที่ได้ ซึ่งจะกลายเป็นอัลกอริธึมแบบผ่านครั้งเดียวสำหรับโมเมนต์ที่สูงขึ้น ข้อดีอย่างหนึ่งคือการคำนวณโมเมนต์ทางสถิติสามารถทำได้ด้วยความแม่นยำตามต้องการ ทำให้สามารถปรับการคำนวณให้เข้ากับความแม่นยำของรูปแบบการจัดเก็บข้อมูลหรือฮาร์ดแวร์การวัดดั้งเดิมได้ ฮิสโตแกรมสัมพัทธ์ของตัวแปรสุ่มสามารถสร้างขึ้นได้ด้วยวิธีทั่วไป: ช่วงของค่าที่เป็นไปได้จะถูกแบ่งออกเป็นช่วงๆ และนับจำนวนครั้งที่เกิดขึ้นภายในแต่ละช่วง แล้วพล็อตโดยให้พื้นที่ของแต่ละสี่เหลี่ยมผืนผ้าเท่ากับส่วนของค่าตัวอย่างภายในช่วงนั้น:
โดยที่และแทนความถี่และความถี่สัมพัทธ์ที่ bin และคือพื้นที่ทั้งหมดของฮิสโตแกรม หลังจากทำการปรับค่าให้เป็นมาตรฐานแล้วสามารถคำนวณ โมเมนต์ดิบและโมเมนต์กลางของ ได้ จากฮิสโตแกรมสัมพัทธ์:
โดยที่ตัวยกแสดงว่าค่าโมเมนต์คำนวณจากฮิสโตแกรม สำหรับความกว้างของช่วงคงที่สามารถลดรูปนิพจน์ทั้งสองนี้ให้ง่ายขึ้นได้โดยใช้:
แนวทางที่สองจาก Choi และ Sweetman [ 15 ]เป็นวิธีการวิเคราะห์เพื่อรวมโมเมนต์ทางสถิติจากแต่ละส่วนของประวัติเวลา โดยที่โมเมนต์โดยรวมที่ได้จะเป็นโมเมนต์ของประวัติเวลาทั้งหมด วิธีการนี้สามารถใช้สำหรับการคำนวณโมเมนต์ทางสถิติแบบขนานและการรวมโมเมนต์เหล่านั้นในภายหลัง หรือสำหรับการรวมโมเมนต์ทางสถิติที่คำนวณในช่วงเวลาต่อเนื่องกัน
หากทราบเซตของโมเมนต์ทางสถิติ: สำหรับแล้วแต่ละโมเมนต์สามารถแสดงได้ในรูปของโมเมนต์ดิบที่เทียบเท่ากัน:
โดยทั่วไปแล้ว จะถือว่า เป็นระยะเวลาของประวัติเวลา หรือจำนวนจุด ถ้ามีค่าคงที่
ข้อดีของการแสดงค่าโมเมนต์ทางสถิติในรูปของคือสามารถนำเซตต่างๆ มาบวกกันได้ และไม่มีขีดจำกัดสูงสุดของค่า
โดยที่ตัวห้อยแสดงถึงประวัติเวลาที่ต่อกันหรือค่าที่รวมกันค่าที่รวมกันเหล่านี้สามารถแปลงกลับเป็นค่าโมเมนต์ดิบที่แสดงถึงประวัติเวลาที่ต่อกันอย่างสมบูรณ์ได้
จากนั้นจะใช้ ความสัมพันธ์ที่ทราบระหว่างโมเมนต์ดิบ ( ) และโมเมนต์กลาง ( ) เพื่อคำนวณโมเมนต์กลางของประวัติเวลาที่เชื่อมต่อกัน สุดท้าย โมเมนต์ทางสถิติของประวัติที่เชื่อมต่อกันจะถูกคำนวณจากโมเมนต์กลาง:
ความแปรปรวนร่วม
สามารถใช้อัลกอริธึมที่คล้ายคลึงกันมากในการคำนวณค่าความแปรปรวนร่วมได้
อัลกอริทึมแบบง่าย
อัลกอริทึมแบบง่ายคือ
สำหรับอัลกอริทึมข้างต้น สามารถใช้โค้ด Python ต่อไปนี้ได้:
def naive_covariance ( data1 , data2 ): n = len ( data1 ) sum1 = sum ( data1 ) sum2 = sum ( data2 ) sum12 = sum ([ i1 * i2 for i1 , i2 in zip ( data1 , data2 )])ความแปรปรวนร่วม= ( ผลรวม12 - ผลรวม1 * ผลรวม2 / n ) / n คืนค่าความแปรปรวนร่วมโดยประมาณค่าเฉลี่ย
ส่วนความแปรปรวนนั้น ความแปรปรวนร่วมของตัวแปรสุ่มสองตัวก็ไม่เปลี่ยนแปลงเมื่อมีการเลื่อนตำแหน่งเช่นกัน ดังนั้นเมื่อกำหนดค่าคงที่สองค่าใดๆก็สามารถเขียนได้ดังนี้:
และการเลือกค่าภายในช่วงค่าอีกครั้งจะช่วยให้สูตรมีความเสถียรมากขึ้น ป้องกันการตัดทอนที่ผิดพลาด และทำให้สูตรมีความแข็งแกร่งมากขึ้นต่อผลรวมขนาดใหญ่ เมื่อพิจารณาค่าแรกของแต่ละชุดข้อมูลอัลกอริทึมสามารถเขียนได้ดังนี้:
def shifted_data_covariance ( data_x , data_y ): n = len ( data_x ) if n < 2 : return 0 kx = data_x [ 0 ] ky = data_y [ 0 ] Ex = Ey = Exy = 0 for ix , iy in zip ( data_x , data_y ): # สำหรับความแม่นยำสูงขึ้น ให้ใช้ sum(): Ex += ix - kx # Ex = sum(ix - kx for ix in data_x) # หรือ sum(ix) - kx * n Ey += iy - ky # Ey = sum(iy - ky for iy in data_y) # หรือ sum(iy) - ky * n Exy += ( ix - kx ) * ( iy - ky ) # Exy = sum((ix - kx) * (iy - ky) for ix, iy in zip(data_x, data_y)) return ( Exy - Ex * อาย/ เอ็น) / เอ็นผ่านสองครั้ง
อัลกอริทึมแบบสองขั้นตอนจะคำนวณค่าเฉลี่ยของตัวอย่างก่อน จากนั้นจึงคำนวณค่าความแปรปรวนร่วม:
อัลกอริทึมแบบสองขั้นตอนสามารถเขียนได้ดังนี้:
def two_pass_covariance ( data1 , data2 ): n = len ( data1 ) mean1 = sum ( data1 ) / n mean2 = sum ( data2 ) / ncovariance = 0 สำหรับi1 , i2 ในzip ( data1 , data2 ): # สำหรับความแม่นยำสูงขึ้น ให้ใช้ sum(): a = i1 - mean1 # covariance = sum((i1 - mean1) * (i2 - mean2) สำหรับ i1, i2 ใน zip(data1, data2)) b = i2 - mean2 covariance += a * b / n return covarianceออนไลน์
มีอัลกอริธึมแบบผ่านครั้งเดียวที่เสถียรอยู่แล้ว ซึ่งคล้ายกับอัลกอริธึมออนไลน์สำหรับการคำนวณความแปรปรวน ที่ใช้ในการคำนวณโคโมเมนต์:
ความไม่สมมาตรที่เห็นได้ชัดในสมการสุดท้ายนั้นเกิดจากข้อเท็จจริงที่ว่าดังนั้นพจน์การปรับปรุงทั้งสองจึงเท่ากับความแม่นยำที่มากขึ้นสามารถทำได้โดยการคำนวณค่าเฉลี่ยก่อน จากนั้นจึงใช้อัลกอริธึมแบบผ่านครั้งเดียวที่เสถียรกับค่าความคลาดเคลื่อน
ดังนั้น ค่าความแปรปรวนร่วมสามารถคำนวณได้ดังนี้
def online_covariance ( data1 , data2 ): meanx = meany = C = n = 0 for x , y in zip ( data1 , data2 ): n += 1 dx = x - meanx meanx += dx / n meany += ( y - meany ) / n C += dx * ( y - meany )# ค่าความแปรปรวนร่วมและการแก้ไขของเบสเซลสำหรับผลตอบแทน ตัวอย่าง ( C / n , C / ( n - 1 ))นอกจากนี้ยังสามารถปรับเปลี่ยนเล็กน้อยเพื่อคำนวณค่าความแปรปรวนร่วมแบบถ่วงน้ำหนักได้:
def online_weighted_covariance ( data1 , data2 , data3 ): meanx = meany = 0 wsum = wsum2 = 0 C = 0 for x , y , w in zip ( data1 , data2 , data3 ): wsum += w wsum2 += w * w dx = x - meanx meanx += ( w / wsum ) * dx meany += ( w / wsum ) * ( y - meany ) C += w * dx * ( y - meany )population_covar = C / wsum # การแก้ไขของเบสเซลสำหรับความแปรปรวนของตัวอย่าง# น้ำหนักความถี่sample_frequency_covar = C / ( wsum - 1 ) # น้ำหนักความน่าเชื่อถือsample_reliability_covar = C / ( wsum - wsum2 / wsum )ในทำนองเดียวกัน มีสูตรสำหรับการรวมความแปรปรวนร่วมของสองชุดที่สามารถใช้เพื่อขนานการคำนวณได้: [ 3 ]
เวอร์ชันแบบกลุ่มถ่วงน้ำหนัก
นอกจากนี้ยังมีเวอร์ชันของอัลกอริธึมแบบถ่วงน้ำหนักออนไลน์ที่ทำการอัปเดตแบบเป็นชุดด้วย โดยให้แทนน้ำหนัก และเขียนว่า
จากนั้นสามารถคำนวณค่าความแปรปรวนร่วมได้ดังนี้
(สามารถใช้ร่วมกับ Python sumเพื่อความแม่นยำยิ่งขึ้น การอัปเดตบล็อกยังเกี่ยวข้องกับอัลกอริธึมแบบขนาน/ผสานด้วย)
ดูเพิ่มเติม
ลิงก์ภายนอก
- ไวส์สไตน์, เอริค ดับเบิลยู. "การคำนวณความแปรปรวนของตัวอย่าง" . MathWorld .
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ อัลกอริทึมสำหรับการคำนวณความแปรปรวน
อัลกอริทึมสำหรับการคำนวณความแปรปรวนมีบทบาทสำคัญในสถิติเชิงคำนวณความยากลำบากที่สำคัญในการออกแบบอัลกอริทึม ที่ดี สำหรับปัญหานี้คือ...
อัลกอริทึมแบบง่าย
สูตรสำหรับการคำนวณความแปรปรวนของ ประชากร ทั้งหมด ที่มีขนาด N คือ:
การคำนวณข้อมูลที่เลื่อนแล้ว
ค่าความแปรปรวน ไม่เปลี่ยนแปลง เมื่อ พารามิเตอร์ตำแหน่ง เปลี่ยนไป ซึ่งเป็นคุณสมบัติที่สามารถนำมาใช้เพื่อหลีกเลี่ยงการหักล้างกันอย่างรุนแรงในสูตรนี้ได้
อัลกอริทึมแบบสองรอบ
แนวทางอื่นที่ใช้สูตรคำนวณความแปรปรวนที่แตกต่างออกไป จะคำนวณค่าเฉลี่ยของตัวอย่างก่อน