2012-05-14 18 views
6

के साथ दिए गए सहसंबंध हैं, एक शैक्षणिक वेबसाइट के लिए, यह मेरा उद्देश्य है कि छात्रों को मूल्य श्रृंखला और उनके सहयोग के साथ कुछ हद तक बेवकूफ बना दिया जाए। उदाहरण के लिए, छात्रों को दो सरणियों जिसके लिए सहसंबंध गणना की जाती है में प्रवेश कर सकते हैं:मूल्यों की एक यादृच्छिक श्रृंखला (बी) की गणना कैसे करें, जिसमें किसी दिए गए श्रृंखला (ए)

$array_x = array(5,3,6,7,4,2,9,5); 
$array_y = array(4,3,4,8,3,2,10,5); 

echo Correlation($array_x, $array_y); // 0.93439982209434 

इस के लिए कोड पूरी तरह से काम करता है और इस पोस्ट के नीचे पाया जा सकता है। हालांकि अब मुझे एक चुनौती का सामना करना पड़ रहा है। क्या मैं चाहता हूँ निम्नलिखित है:

  • छात्र एक $ श्रेणी_ आदानों (5,3,6,7,4,2,9,5)
  • छात्र एक संबंध आदानों (0,9)
  • छात्र आदानों $ array_y की सीमाएं (उदाहरण के लिए, 1 और 10 के बीच या 50 से 80 के बीच)
  • स्क्रिप्ट एक यादृच्छिक सरणी देता है (उदाहरण के लिए: 4,3,4,8,3,2,10,5) जिसमें (के बारे में) दिए गए सहसंबंध

तो, दूसरे शब्दों में, कोड को काम करना होगा:

$array_x = array(5,3,6,7,4,2,9,5); 
$boundaries = array(1, 10); 
$correlation = 0.9; 

echo ySeries($array_x, $boundaries, $correlation); // array(4,3,4,8,3,2,10,5) 

Stackexchange मठ मंच पर, @ilya (एक छवि के रूप में सम्मिलित किया गया है, क्योंकि fomulas की लेटेक्स स्वरूपण stackoverflow पर काम करने के लिए नहीं है) उसका उत्तर:

enter image description here

पी.एस. सहसंबंध की गणना करने के लिए प्रयोग किया जाता कोड:,

function Correlation($arr1, $arr2) {   
    $correlation = 0; 
    $k = SumProductMeanDeviation($arr1, $arr2); 
    $ssmd1 = SumSquareMeanDeviation($arr1); 
    $ssmd2 = SumSquareMeanDeviation($arr2); 
    $product = $ssmd1 * $ssmd2; 
    $res = sqrt($product); 
    $correlation = $k/$res; 

    return $correlation; 
} 

function SumProductMeanDeviation($arr1, $arr2) { 
    $sum = 0; 
    $num = count($arr1); 
    for($i=0; $i < $num; $i++) { 
    $sum = $sum + ProductMeanDeviation($arr1, $arr2, $i); 
    } 
    return $sum; 
} 

function ProductMeanDeviation($arr1, $arr2, $item) { 
    return (MeanDeviation($arr1, $item) * MeanDeviation($arr2, $item)); 
} 

function SumSquareMeanDeviation($arr) { 
    $sum = 0; 
    $num = count($arr); 
    for($i = 0; $i < $num; $i++) { 
    $sum = $sum + SquareMeanDeviation($arr, $i); 
    } 
    return $sum; 
} 

function SquareMeanDeviation($arr, $item) { 
    return MeanDeviation($arr, $item) * MeanDeviation($arr, $item); 
} 

function SumMeanDeviation($arr) { 
    $sum = 0; 
    $num = count($arr); 
    for($i = 0; $i < $num; $i++) { 
    $sum = $sum + MeanDeviation($arr, $i); 
    } 
    return $sum; 
} 

function MeanDeviation($arr, $item) { 
    $average = Average($arr); 
    return $arr[$item] - $average; 
}  

function Average($arr) { 
    $sum = Sum($arr); 
    $num = count($arr); 
    return $sum/$num; 
} 

function Sum($arr) { 
    return array_sum($arr); 
} 
+0

इस समस्या के बारे में दिलचस्प क्या है कि आप एक उपकरण के साथ छात्रों को प्रदान करने का एक तरीका ढूंढ रहे हैं, यदि मैं सही प्रश्न पढ़ रहा हूं, तो पूर्व परिभाषित गणितीय समाधान नहीं है (जो है कहें, 500+ साल पहले कुछ यूनानी या फ्रेंच लड़के के साथ कोई समीकरण या कार्य नहीं हुआ था)। जबकि इसे खींचने के लक्ष्य का लक्ष्य महान है (और मैं इसके बारे में सोचने जा रहा हूं), आप मूल रूप से एक टूल/फ़ंक्शन प्रदान कर रहे हैं जिसे छात्र वास्तव में प्राप्त नहीं कर सके (दूसरे शब्दों में, वे ' पुष्टि करने के लिए पहले से ही अपनी सूची बनाने की पुष्टि करने के लिए संख्याओं में प्लग करें। – Anthony

+0

यदि मैं आपकी टिप्पणी को सही ढंग से समझता हूं, तो इस उपकरण का उद्देश्य उदाहरण के लिए, यह दर्शाता है कि यदि श्रृंखला ए 300 और 500 के बीच है, तो यह श्रृंखला बी के साथ सहसंबंधित हो सकता है कि बी की सीमाएं 1 से 10 या बहुत अधिक हैं , 700 से 1000 कहें। मैंने अर्थशास्त्र का अध्ययन किया, और कई गणनाओं को उपकरण रखने से सबसे अच्छी तरह समझा गया जो आपको दूसरे गुणों के परिणाम देखने के लिए कुछ गुणों के साथ परेशान करते हैं। कुछ ग्रीक या फ्रांसीसी लोगों के प्रमेय को प्रमाण प्रदान करने के बजाए यह टूल का उद्देश्य होगा :-) – Pr0no

+0

मैं निश्चित रूप से सभी कोणों से प्रमेय के साथ खेलने का लाभ समझता हूं। यह निश्चित रूप से मुझे अन्य मॉडलों/प्रणालियों के बीच उन्नत ज्यामिति (पुनः: मूल ट्रिगर) को बेहतर समझने में मदद मिली है। मुझे आश्चर्य है कि आपका प्रश्न प्रोग्रामिंग समस्या इतनी ज्यादा नहीं है क्योंकि यह गणितीय है।मेरे पास कुछ मौकों पर एहसास हुआ है कि मेरे स्वयं के दुविधाओं के बारे में, और पाया कि [गणित] (math.stackexchange.com) से पूछने से मुझे शीर्ष पर कोड बनाने के लिए बेहतर नींव बनाने में मदद मिली। जैसे मैंने कहा, मुझे लगता है कि सवाल मान्य है और लक्ष्य महान है, लेकिन जवाब कोडिंग से शायद अधिक मौलिक है। – Anthony

उत्तर

4

तो काम हो सकता है, यहाँ डॉकिंस 'weasel का उपयोग करता है वांछित सीमा तक धीरे-धीरे त्रुटि को कम करने के लिए अपने एल्गोरिथ्म के php कार्यान्वयन है ।

<?php 
function sqrMeanDeviation($array, $avg) 
{ 
    $sqrMeanDeviation = 0; 
    for($i=0; $i<count($array); $i++) 
    { 
     $dev = $array[$i] - $avg; 
     $sqrMeanDeviation += $dev * $dev; 
    } 

    return $sqrMeanDeviation; 
} 

// z values are non-0 an can value between [-abs_z_bound, abs_z_bound] 
function random_z_element($abs_z_bound = 1) 
{ 
    $a = (mt_rand() % (2*$abs_z_bound)) - ($abs_z_bound-1); 
    if($a <= 0) 
     $a--; 
    return $a; 
} 

// change z a little 
function copy_z_weasel($old_array_z, $error_probability = 20 /*error possible is 1 in error_probability*/, $abs_z_bound = 1) 
{ 
    $new_z = array(); 

    for($i = 0; $i < count($old_array_z); $i++) 
     if(mt_rand() % $error_probability == 0) 
      $new_z[$i] = random_z_element($abs_z_bound); 
     else 
      $new_z[$i] = $old_array_z[$i]; 

    return $new_z; 
} 

function correlation_error($array_y, $array_x, $avg_x, $sqrMeanDeviation_x, $correlation) 
{ 
    // checking correlation 
    $avg_y = array_sum($array_y)/count($array_y); 

    $sqrMeanDeviation_y = 0; 
    $covariance_xy = 0; 

    for($i=0; $i<count($array_x); $i++) 
    { 
     $dev_y = $array_y[$i] - $avg_y; 
     $sqrMeanDeviation_y += $dev_y * $dev_y; 

     $dev_x = $array_x[$i] - $avg_x; 
     $covariance_xy += $dev_y * $dev_x; 
    } 
    $correlation_xy = $covariance_xy/sqrt($sqrMeanDeviation_x*$sqrMeanDeviation_y); 
    return abs($correlation_xy - $correlation); 
} 

function ySeries($array_x, $low_bound, $high_bound, $correlation, $threshold) 
{ 
    $array_y = array(); 

    $avg_x = array_sum($array_x)/count($array_x); 
    $sqrMeanDeviation_x = sqrMeanDeviation($array_x, $avg_x); 

    // pre-compute beta 
    $beta_x_sQMz = $sqrMeanDeviation_x * sqrt(1/($correlation*$correlation) - 1); 

    $best_array_z = array(); 
    $n = 0; 
    $error = $threshold + 1; 

    while($error > $threshold) 
    { 
     ++$n; 

     // generate z 
     $array_z = array(); 
     if(count($best_array_z) == 0) 
      for($i=0; $i<count($array_x); $i++) 
       $array_z[$i] = random_z_element(); 
     else 
      $array_z = copy_z_weasel($best_array_z); 

     $sqm_z = sqrMeanDeviation($array_z, array_sum($array_z)/count($array_z)); 
     // this being 0 implies that for every beta correlation(x,y) = 1 so just give it any random beta 
     if($sqm_z) 
      $beta = $beta_x_sQMz/$sqm_z; 
     else 
      $beta = 10; 
     // and now we have y 
     for($i=0; $i<count($array_x); $i++) 
      $array_y[$i] = $array_x[$i] + ($array_z[$i] * $beta); 

     // now, change bounds (we could do this afterwards but we want precision and y to be integers) 
     // rounding 
     $min_y = $array_y[0]; 
     $max_y = $array_y[0]; 
     for($i=1; $i<count($array_x); $i++) 
     { 
      if($array_y[$i] < $min_y) 
       $min_y = $array_y[$i]; 
      if($array_y[$i] > $max_y) 
       $max_y = $array_y[$i]; 
     } 

     $range = ($high_bound - $low_bound)/($max_y - $min_y); 
     $shift = $low_bound - $min_y; 
     for($i=0; $i<count($array_x); $i++) 
      $array_y[$i] = round($array_y[$i] * $range + $shift); 

     // get the error 
     $new_error = correlation_error($array_y, $array_x, $avg_x, $sqrMeanDeviation_x, $correlation); 

     if($new_error < $error) 
     { 
      $best_array_z = $array_z; 
      $error = $new_error; 
     } 

    } 
    echo "Correlation ", $correlation, " approched within " , $new_error, " in ", $n ," iterations.\n"; 

    return $array_y; 
} 

?> 
+0

धन्यवाद! लेकिन जो मुझे समझ में नहीं आता ... आप 0.001 के औसत अंतर को बोलते हैं ... 0.7 के अनुरोधित सहसंबंध पर मुझे -0.1 और 0.8 के बीच कई अंतर मिलते हैं। आपके परिणामों के साथ इतना अंतर कैसे है? मैं आपके कोड का उपयोग '$ array_x = array (5,3,6,7,4,2,9,5) के साथ कर रहा हूं; $ low_bound = 100; $ high_bound = 130; $ सहसंबंध = 0.7; 'कोई विचार? क्या एल्गोरिदम सटीकता को बढ़ाने के लिए संभव है या फ़ंक्शन को दोहराएं यदि सहसंबंध में एक निश्चित दहलीज से अधिक अंतर है, तो 0.05 कहें? – Pr0no

+0

मैं त्रुटि के भिन्नता से आश्चर्यचकित हूं (मान abs ($ correlation_xy - $ सहसंबंध)) लेकिन मैंने केवल एक त्वरित परीक्षण किया, जिसमें बड़ी संख्या में यादृच्छिक इनपुट मान (array_x और सहसंबंध) और औसत त्रुटि कम थी। यही कारण है कि मैंने सुझाव दिया कि आप अधिकतम त्रुटि को नियंत्रित करने के लिए एक लूप जोड़ें। लेकिन मैं इसे शामिल करने के लिए संपादित करूंगा क्योंकि मुझे एलेक्स के विचार पसंद हैं। – Cimbali

3

एक सरल दृष्टिकोण हालांकि बहुत अक्षम, दिए गए अंतराल में एक यादृच्छिक संख्या के साथ शुरू और अधिक संख्या में जोड़ने के लिए प्रयास करने के लिए, जब तक हो जाएगा के रूप में वे का उल्लंघन नहीं करते सहसंबंध बहुत ज्यादा:

function ySeries(array_x, boundaries, correlation) { 
    array_y = [random(boundaries)] 
    while (len(array_y) < len(array_x)) { 
    do {  
     y = random(boundaries) 
    } while (Correlation(array_x, array_y + [y]) > correlation + epsilon) 

    array_y.push(y) 
    } 
} 

अच्छी तरह से, जब तक कि संख्या छोटे हैं

+0

एक संस्करण के रूप में: array_y = array_x प्रारंभ करें और उपरोक्त के समान रूप में मूल्यों को यादृच्छिक रूप से परेशान करें, सहसंबंध को नियंत्रित करें। – Pavel

+0

क्या आप विस्तृत कर सकते हैं? आप ईपीएसलॉन कहां से प्राप्त करते हैं? – Pr0no

+0

यह दिए गए सहसंबंध से विचलन है जिसे आप सहन करना चाहते हैं, जो आपके द्वारा चुने गए निरंतर हैं। कुछ और होना चाहिए ... जबकि | सहसंबंध (..) - सहसंबंध | > epsilon – Pavel

संबंधित मुद्दे