воскресенье, 12 марта 2017 г.

Линейная регрессия онлайн


Методы регрессионного анализа к прикладной газовой динамике имеют несколько опосредованное отношение, однако без этих механизмов практически невозможно выполнить анализ работы оборудования газотранспортной системы (газоперекачивающих агрегатов, пылеуловителей) или физических процессов в «трубе» (выявление и предупреждение гидратообразования в газопроводе).
Некоторое время назад в категории OpenSource-продуктов появился написанный на Object Pascal прекрасный математический модуль DMath (автор: Dr Jean DEBORD, Laboratoire de Pharmacologie, Faculte de Medecine 2 Rue du Docteur Marcland, 87025 Limoges, France). В этом модуле много чего интересного (решение нелинейных уравнений, расчет определенного интеграла), но в первую очередь востребованы реализованные в нем методы регрессионного анализа. Вот их неполный перечень:
  • Линейная регрессия;
  • Полиномиальная регрессия;
  • Степенная регрессия;
  • Гамма-регрессия.
Здесь перечислены только те методы регрессионного анализа, которые удалось портировать с Object Pascal в PHP и реализовать в виде онлайн-расчетов на сайте.
Итак, линейная регрессия. Искомая зависимость:

Ссылка на страницу с онлайн-расчетом:


Что имеем в результате расчета (по выбору пользователя можно просто вывести в небольшом окне, а можно сохранить вместе с исходными данными в RTF-файл):


Исходный код (PHP):
<?php
<?php
// Линейная регрессия
header('Content-Type^ text/html; charset=utf-8');
if ($_SERVER['HTTP_X_REQUESTED_WITH']=='XMLHttpRequest'){
        if ($_POST){
               $dimdata = $_POST['dimdata'];// массив данных (абцисса и ордината) из таблицы
               $deg = $_POST['deg'];// степень полинома. Конкретно для линейной регрессии - 1.
               //
               // уборщик "мусора" в temp
               // источник:
               // http://itheap.info/blog/web-master-blog/154.html
               function clearTEMP() {
               $dir = 'temp';
                       $files = scandir($dir); // сканирование файлов в папке и создание списка
               unset($files[0], $files[1]); // удаление из списка (массива) элементов ".",".."
               foreach ($files as $fname) { // цикл по списку файлов
                $filename = $dir .'/'. $fname; // создаем полный путь к файлу
                if (file_exists($filename)) { // проверяем наличии файла, за это время он уже мог удалиться
                    $ftime = filemtime($filename); // определяем время создания/изменения файла
                    $d_time = time() - $ftime; //определяем разницу между текущим временем и временем создания файла
                    if ($d_time > 600) { //условие - если время больше чем [разница в сек] (10мин)
                        @unlink($filename); // удаляем файл
                    }//if
                } //if
               }//foreach
        }
               //
               $B0 = 0;
               $B1 = 0;
               $filepng = 'xx';
               $rcount = count($dimdata)/2;// количество пар значений
               $Lb = 0; $Ub = $rcount-1;
               $N = $Ub-$Lb+1;
        $SX = 0;
        $SY = 0;
        $SX2 = 0;
        $SXY = 0;
               for ($K=0; $K<=$Ub; $K++){
                       $SX = $SX+$dimdata[$K*2];
               $SY = $SY+$dimdata[$K*2+1];
               $SX2= $SX2+$dimdata[$K*2]*$dimdata[$K*2];
               $SXY= $SXY+$dimdata[$K*2]*$dimdata[$K*2+1];
                       //
                       $xx[$K] = $dimdata[$K*2];
                       $yy[$K] = $dimdata[$K*2+1]; 
               }
        $D = $N*$SX2-$SX*$SX;
               if ($D <= 0){
                       $ErrCode = 'Квази-сингулярная матрица';
               } else {
                       $ErrCode = '1';
                       $V0 = $SX2/$D;
               $V1 = -$SX/$D;
               $V2 = $V1;
               $V3 = $N/$D;
            //коэффициенты полинома:
                       $B0 = $V0*$SY+$V1*$SXY;
               $B1 = $V2*$SY+$V3*$SXY;
                       //
                       clearTEMP();
                       // Построение графика:
                       // Утилита PChart. Для использования в php.ini
                       // необходимо подключить php_gd2.dll.
                       //
                       // Standard inclusions   
                       include("pChart/pData.class");
                       include("pChart/pChart.class");
                       // Dataset definition 
                       $DataSet = new pData;
                       for ($K=0; $K<=$Ub; $K++){
                               $DataSet->AddPoint($xx[$K],"abscise");
                               $DataSet->AddPoint($yy[$K],"indata");
                               $DataSet->AddPoint($B1*$xx[$K]+$B0,"outdata");
                       }
                       $DataSet->AddAllSeries();     
                       $DataSet->SetAbsciseLabelSerie();     
                       $DataSet->SetSerieName("сходные данные","indata");     
                       $DataSet->SetSerieName("Результат расчета","outdata");
                       $DataSet->SetXAxisName("абцисса");       
                       $DataSet->SetYAxisName("ордината");  
                       // Initialise the graph 
                       $Test = new pChart(600,233);
                       $Test->setColorPalette(0,0,0,200);
                       $Test->setColorPalette(1,200,0,0);     
                       $Test->setFontProperties("Fonts/tahoma.ttf",8);     
                       $Test->setGraphArea(70,30,580,190);     
                       $Test->drawFilledRoundedRectangle(7,7,593,228,1,240,240,240);     
                       $Test->drawRoundedRectangle(5,5,595,230,3,128,57,67);     
                       $Test->drawGraphArea(250,250,250,FALSE);  
                       $Test->drawXYScale($DataSet->GetData(),$DataSet->GetDataDescription(),"indata","abscise",100,100,100,TRUE,0);                          
                       $Test->drawGrid(3,FALSE,128,57,67,0);                        
                       // Draw the 0 line     
                       $Test->setFontProperties("Fonts/tahoma.ttf",6);     
                       $Test->drawTreshold(0,50,50,50,TRUE,TRUE);        
                       // Draw the line graph  
                       $Test->drawXYPlotGraph($DataSet->GetData(),$DataSet->GetDataDescription(),"indata","abscise",0,2,1,230,230,230);         
                       $Test->drawXYGraph($DataSet->GetData(),$DataSet->GetDataDescription(),"outdata","abscise",1);
                       // Finish the graph     
                       $Test->setFontProperties("Fonts/tahoma.ttf",8);
                       $DataSet->RemoveSerie("abscise");
                       $Test->drawLegend(75,35,$DataSet->GetDataDescription(),240,240,240);     
                       $Test->setFontProperties("Fonts/tahoma.ttf",10);     
                       $Test->drawTitle(60,22,"Линейная регрессия",10,10,10,585);
                       //
                       $file = substr(md5(microtime() . rand(0, 9999)), 0, 12);
                       //
                       $filepng = 'temp/chart_'.$file.'.'.'png';     
                       $Test->Render($filepng);
                       }
               $B0 = str_replace(".", ",", $B0);
               $B1 = str_replace(".", ",", $B1);
               //
               echo json_encode(array($ErrCode, $B0, $B1, $filepng));
        }
}
?>