31

Oracleの線形回帰関数と同様に、SQL Server 2005/2008に線形回帰関数はありますか?

4

8 に答える 8

46

私の知る限り、何もありません。ただし、作成するのは非常に簡単です。以下は、y=アルファ+ベータ*x+イプシロンの定数アルファと勾配ベータを示します。

-- test data (GroupIDs 1, 2 normal regressions, 3, 4 = no variance)
WITH some_table(GroupID, x, y) AS
(       SELECT 1,  1,  1    UNION SELECT 1,  2,  2    UNION SELECT 1,  3,  1.3  
  UNION SELECT 1,  4,  3.75 UNION SELECT 1,  5,  2.25 UNION SELECT 2, 95, 85    
  UNION SELECT 2, 85, 95    UNION SELECT 2, 80, 70    UNION SELECT 2, 70, 65    
  UNION SELECT 2, 60, 70    UNION SELECT 3,  1,  2    UNION SELECT 3,  1, 3
  UNION SELECT 4,  1,  2    UNION SELECT 4,  2,  2),
 -- linear regression query
/*WITH*/ mean_estimates AS
(   SELECT GroupID
          ,AVG(x * 1.)                                             AS xmean
          ,AVG(y * 1.)                                             AS ymean
    FROM some_table
    GROUP BY GroupID
),
stdev_estimates AS
(   SELECT pd.GroupID
          -- T-SQL STDEV() implementation is not numerically stable
          ,CASE      SUM(SQUARE(x - xmean)) WHEN 0 THEN 1 
           ELSE SQRT(SUM(SQUARE(x - xmean)) / (COUNT(*) - 1)) END AS xstdev
          ,     SQRT(SUM(SQUARE(y - ymean)) / (COUNT(*) - 1))     AS ystdev
    FROM some_table pd
    INNER JOIN mean_estimates  pm ON pm.GroupID = pd.GroupID
    GROUP BY pd.GroupID, pm.xmean, pm.ymean
),
standardized_data AS                   -- increases numerical stability
(   SELECT pd.GroupID
          ,(x - xmean) / xstdev                                    AS xstd
          ,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd
    FROM some_table pd
    INNER JOIN stdev_estimates ps ON ps.GroupID = pd.GroupID
    INNER JOIN mean_estimates  pm ON pm.GroupID = pd.GroupID
),
standardized_beta_estimates AS
(   SELECT GroupID
          ,CASE WHEN SUM(xstd * xstd) = 0 THEN 0
                ELSE SUM(xstd * ystd) / (COUNT(*) - 1) END         AS betastd
    FROM standardized_data pd
    GROUP BY GroupID
)
SELECT pb.GroupID
      ,ymean - xmean * betastd * ystdev / xstdev                   AS Alpha
      ,betastd * ystdev / xstdev                                   AS Beta
FROM standardized_beta_estimates pb
INNER JOIN stdev_estimates ps ON ps.GroupID = pb.GroupID
INNER JOIN mean_estimates  pm ON pm.GroupID = pb.GroupID

GroupIDこれは、ソースデータテーブルの値でグループ化する方法を示すために使用されます。テーブル内のすべてのデータ(特定のサブグループではない)の統計が必要な場合は、それと結合を削除できます。WITHわかりやすくするために、このステートメントを使用しました。別の方法として、代わりにサブクエリを使用できます。データに対して精度が十分に高くないと、数値の安定性が急速に低下する可能性があるため、テーブルで使用されるデータ型の精度に注意してください。

編集:(コメントのR2のような追加の統計に関するPeterの質問への回答)

同じ手法を使用して、追加の統計を簡単に計算できます。これは、R2、相関、およびサンプル共分散を含むバージョンです。

-- test data (GroupIDs 1, 2 normal regressions, 3, 4 = no variance)
WITH some_table(GroupID, x, y) AS
(       SELECT 1,  1,  1    UNION SELECT 1,  2,  2    UNION SELECT 1,  3,  1.3  
  UNION SELECT 1,  4,  3.75 UNION SELECT 1,  5,  2.25 UNION SELECT 2, 95, 85    
  UNION SELECT 2, 85, 95    UNION SELECT 2, 80, 70    UNION SELECT 2, 70, 65    
  UNION SELECT 2, 60, 70    UNION SELECT 3,  1,  2    UNION SELECT 3,  1, 3
  UNION SELECT 4,  1,  2    UNION SELECT 4,  2,  2),
 -- linear regression query
/*WITH*/ mean_estimates AS
(   SELECT GroupID
          ,AVG(x * 1.)                                             AS xmean
          ,AVG(y * 1.)                                             AS ymean
    FROM some_table pd
    GROUP BY GroupID
),
stdev_estimates AS
(   SELECT pd.GroupID
          -- T-SQL STDEV() implementation is not numerically stable
          ,CASE      SUM(SQUARE(x - xmean)) WHEN 0 THEN 1 
           ELSE SQRT(SUM(SQUARE(x - xmean)) / (COUNT(*) - 1)) END AS xstdev
          ,     SQRT(SUM(SQUARE(y - ymean)) / (COUNT(*) - 1))     AS ystdev
    FROM some_table pd
    INNER JOIN mean_estimates  pm ON pm.GroupID = pd.GroupID
    GROUP BY pd.GroupID, pm.xmean, pm.ymean
),
standardized_data AS                   -- increases numerical stability
(   SELECT pd.GroupID
          ,(x - xmean) / xstdev                                    AS xstd
          ,CASE ystdev WHEN 0 THEN 0 ELSE (y - ymean) / ystdev END AS ystd
    FROM some_table pd
    INNER JOIN stdev_estimates ps ON ps.GroupID = pd.GroupID
    INNER JOIN mean_estimates  pm ON pm.GroupID = pd.GroupID
),
standardized_beta_estimates AS
(   SELECT GroupID
          ,CASE WHEN SUM(xstd * xstd) = 0 THEN 0
                ELSE SUM(xstd * ystd) / (COUNT(*) - 1) END         AS betastd
    FROM standardized_data
    GROUP BY GroupID
)
SELECT pb.GroupID
      ,ymean - xmean * betastd * ystdev / xstdev                   AS Alpha
      ,betastd * ystdev / xstdev                                   AS Beta
      ,CASE ystdev WHEN 0 THEN 1 ELSE betastd * betastd END        AS R2
      ,betastd                                                     AS Correl
      ,betastd * xstdev * ystdev                                   AS Covar
FROM standardized_beta_estimates pb
INNER JOIN stdev_estimates ps ON ps.GroupID = pb.GroupID
INNER JOIN mean_estimates  pm ON pm.GroupID = pb.GroupID

EDIT 2は、データを(中央揃えだけでなく)標準化し、数値安定性の問題のために置き換えるSTDEVことにより、数値安定性を向上させます。私には、現在の実装が安定性と複雑さの間の最良のトレードオフのように思われます。標準偏差を数値的に安定したオンラインアルゴリズムに置き換えることで安定性を向上させることができますが、これは実装を実質的に複雑にします(そしてそれを遅くします)。同様に、たとえばKahan(-Babuška-Neumaier)補正を使用した実装は、限られたテストで適度にパフォーマンスが向上するようSUMAVG見えますが、クエリははるかに複雑になります。そして、T-SQLがどのように実装されているかわからない限りSUMAVG(たとえば、すでにペアワイズ合計を使用している可能性があります)、そのような変更が常に精度を向上させることを保証することはできません。

于 2010-03-29T09:58:00.703 に答える
24

これは、 T-SQLの線形回帰に関するブログ投稿に基づく代替方法であり、次の方程式を使用します。

ここに画像の説明を入力してください

ただし、ブログのSQLの提案ではカーソルを使用しています。これが私が使用したフォーラムの回答のきれいなバージョンです:

table
-----
X (numeric)
Y (numeric)

/**
 * m = (nSxy - SxSy) / (nSxx - SxSx)
 * b = Ay - (Ax * m)
 * N.B. S = Sum, A = Mean
 */
DECLARE @n INT
SELECT @n = COUNT(*) FROM table
SELECT (@n * SUM(X*Y) - SUM(X) * SUM(Y)) / (@n * SUM(X*X) - SUM(X) * SUM(X)) AS M,
       AVG(Y) - AVG(X) *
       (@n * SUM(X*Y) - SUM(X) * SUM(Y)) / (@n * SUM(X*X) - SUM(X) * SUM(X)) AS B
FROM table
于 2010-07-19T16:51:44.500 に答える
5

私は実際にグラムシュミットオルソガナリゼーションを使用してSQLルーチンを作成しました。これは、他の機械学習および予測ルーチンと同様に、sqldatamine.blogspot.comで入手できます。

Brad Larsonの提案で、ユーザーをブログに誘導するだけでなく、ここにコードを追加しました。これにより、Excelのlinet関数と同じ結果が得られます。私の主な情報源は、Hastie、Tibshirni、FriedmanによるElements of Statistics Learning(2008)です。

--Create a table of data
create table #rawdata (id int,area float, rooms float, odd float,  price float)

insert into #rawdata select 1, 2201,3,1,400
insert into #rawdata select 2, 1600,3,0,330
insert into #rawdata select 3, 2400,3,1,369
insert into #rawdata select 4, 1416,2,1,232
insert into #rawdata select 5, 3000,4,0,540

--Insert the data into x & y vectors
select id xid, 0 xn,1 xv into #x from #rawdata
union all
select id, 1,rooms  from #rawdata
union all
select id, 2,area  from #rawdata
union all
select id, 3,odd  from #rawdata

select id yid, 0 yn, price yv  into #y from #rawdata

--create a residuals table and insert the intercept (1)
create table #z (zid int, zn int, zv float)
insert into #z select id , 0 zn,1 zv from #rawdata

--create a table for the orthoganal (#c) & regression(#b) parameters
create table #c(cxn int, czn int, cv float) 
create table #b(bn int, bv float) 


--@p is the number of independent variables including the intercept (@p = 0)
declare @p int
set @p = 1


--Loop through each independent variable and estimate the orthagonal parameter (#c)
-- then estimate the residuals and insert into the residuals table (#z)
while @p <= (select max(xn) from #x)
begin   
        insert into #c
    select  xn cxn,  zn czn, sum(xv*zv)/sum(zv*zv) cv 
        from #x join  #z on  xid = zid where zn = @p-1 and xn>zn group by xn, zn

    insert into #z
    select zid, xn,xv- sum(cv*zv) 
        from #x join #z on xid = zid   join  #c  on  czn = zn and cxn = xn  where xn = @p and zn<xn  group by zid, xn,xv

    set @p = @p +1
end

--Loop through each independent variable and estimate the regression parameter by regressing the orthoganal
-- resiuduals on the dependent variable y
while @p>=0 
begin

    insert into #b
    select zn, sum(yv*zv)/ sum(zv*zv) 
        from #z  join 
            (select yid, yv-isnull(sum(bv*xv),0) yv from #x join #y on xid = yid left join #b on  xn=bn group by yid, yv) y
        on zid = yid where zn = @p  group by zn

    set @p = @p-1
end

--The regression parameters
select * from #b

--Actual vs. fit with error
select yid, yv, fit, yv-fit err from #y join 
    (select xid, sum(xv*bv) fit from #x join #b on xn = bn  group by xid) f
     on yid = xid

--R Squared
select 1-sum(power(err,2))/sum(power(yv,2)) from 
(select yid, yv, fit, yv-fit err from #y join 
    (select xid, sum(xv*bv) fit from #x join #b on xn = bn  group by xid) f
     on yid = xid) d
于 2014-01-07T18:07:00.673 に答える
3

SQLServerには線形回帰関数はありません。ただし、データポイントx、yのペア間の単純線形回帰(Y'= bX + A)を計算するには、相関係数、決定係数(R ^ 2)、および標準偏差の推定(標準偏差)の計算を含みます。以下をせよ:

regression_data数値列xy:を含むテーブルの場合

declare @total_points int 
declare @intercept DECIMAL(38, 10)
declare @slope DECIMAL(38, 10)
declare @r_squared DECIMAL(38, 10)
declare @standard_estimate_error DECIMAL(38, 10)
declare @correlation_coefficient DECIMAL(38, 10)
declare @average_x  DECIMAL(38, 10)
declare @average_y  DECIMAL(38, 10)
declare @sumX DECIMAL(38, 10)
declare @sumY DECIMAL(38, 10)
declare @sumXX DECIMAL(38, 10)
declare @sumYY DECIMAL(38, 10)
declare @sumXY DECIMAL(38, 10)
declare @Sxx DECIMAL(38, 10)
declare @Syy DECIMAL(38, 10)
declare @Sxy DECIMAL(38, 10)

Select 
@total_points = count(*),
@average_x = avg(x),
@average_y = avg(y),
@sumX = sum(x),
@sumY = sum(y),
@sumXX = sum(x*x),
@sumYY = sum(y*y),
@sumXY = sum(x*y)
from regression_data

set @Sxx = @sumXX - (@sumX * @sumX) / @total_points
set @Syy = @sumYY - (@sumY * @sumY) / @total_points
set @Sxy = @sumXY - (@sumX * @sumY) / @total_points

set @correlation_coefficient = @Sxy / SQRT(@Sxx * @Syy) 
set @slope = (@total_points * @sumXY - @sumX * @sumY) / (@total_points * @sumXX - power(@sumX,2))
set @intercept = @average_y - (@total_points * @sumXY - @sumX * @sumY) / (@total_points * @sumXX - power(@sumX,2)) * @average_x
set @r_squared = (@intercept * @sumY + @slope * @sumXY - power(@sumY,2) / @total_points) / (@sumYY - power(@sumY,2) / @total_points)

-- calculate standard_estimate_error (standard deviation)
Select
@standard_estimate_error = sqrt(sum(power(y - (@slope * x + @intercept),2)) / @total_points)
From regression_data
于 2014-04-02T01:27:43.623 に答える
2

これは、次のタイプのテーブルタイプをとる関数です。XYDoubleTypeと呼ばれるtable(Y float、X double)であり、線形関数はAX+Bの形式であると想定しています。万が一の場合に備えてAとBにTable列を返します。あなたはそれを結合か何かに入れたい

CREATE FUNCTION FN_GetABForData(
 @XYData as XYDoubleType READONLY
 ) RETURNS  @ABData TABLE(
            A  FLOAT,
            B FLOAT, 
            Rsquare FLOAT )
 AS
 BEGIN
    DECLARE @sx FLOAT, @sy FLOAT
    DECLARE @sxx FLOAT,@syy FLOAT, @sxy FLOAT,@sxsy FLOAT, @sxsx FLOAT, @sysy FLOAT
    DECLARE @n FLOAT, @A FLOAT, @B FLOAT, @Rsq FLOAT

    SELECT @sx =SUM(D.X) ,@sy =SUM(D.Y), @sxx=SUM(D.X*D.X),@syy=SUM(D.Y*D.Y),
        @sxy =SUM(D.X*D.Y),@n =COUNT(*)
    From @XYData D
    SET @sxsx =@sx*@sx
    SET @sxsy =@sx*@sy
    SET @sysy = @sy*@sy

    SET @A = (@n*@sxy -@sxsy)/(@n*@sxx -@sxsx)
    SET @B = @sy/@n  - @A*@sx/@n
    SET @Rsq = POWER((@n*@sxy -@sxsy),2)/((@n*@sxx-@sxsx)*(@n*@syy -@sysy))

    INSERT INTO @ABData (A,B,Rsquare) VALUES(@A,@B,@Rsq)

    RETURN 
 END
于 2013-04-25T22:16:05.377 に答える
2

@ icc97の回答に追加するために、勾配と切片の加重バージョンを含めました。値がすべて一定の場合、勾配は(適切な設定でSET ARITHABORT OFF; SET ANSI_WARNINGS OFF;)NULLになり、coalesce()を介して0に置き換える必要があります。

SQLで記述されたソリューションは次のとおりです。

with d as (select segment,w,x,y from somedatasource)
select segment,

avg(y) - avg(x) *
((count(*) * sum(x*y)) - (sum(x)*sum(y)))/
((count(*) * sum(x*x)) - (Sum(x)*Sum(x)))   as intercept,

((count(*) * sum(x*y)) - (sum(x)*sum(y)))/
((count(*) * sum(x*x)) - (sum(x)*sum(x))) AS slope,

avg(y) - ((avg(x*y) - avg(x)*avg(y))/var_samp(X)) * avg(x) as interceptUnstable,
(avg(x*y) - avg(x)*avg(y))/var_samp(X) as slopeUnstable,
(Avg(x * y) - Avg(x) * Avg(y)) / (stddev_pop(x) * stddev_pop(y)) as correlationUnstable,

(sum(y*w)/sum(w)) - (sum(w*x)/sum(w)) *
((sum(w)*sum(x*y*w)) - (sum(x*w)*sum(y*w)))/
  ((sum(w)*sum(x*x*w)) - (sum(x*w)*sum(x*w)))   as wIntercept,

((sum(w)*sum(x*y*w)) - (sum(x*w)*sum(y*w)))/
  ((sum(w)*sum(x*x*w)) - (sum(x*w)*sum(x*w))) as wSlope,

(count(*) * sum(x * y) - sum(x) * sum(y)) / (sqrt(count(*) * sum(x * x) - sum(x) * sum(x))
* sqrt(count(*) * sum(y * y) - sum(y) * sum(y))) as correlation,

(sum(w) * sum(x*y*w) - sum(x*w) * sum(y*w)) /
(sqrt(sum(w) * sum(x*x*w) - sum(x*w) * sum(x*w)) * sqrt(sum(w) * sum(y*y*w)
- sum(y*w) * sum(y*w))) as wCorrelation,

count(*) as n

from d where x is not null and y is not null group by segment

ここで、wは重量です。結果を確認するために、これをRに対して再確認しました。somedatasourceから浮動小数点にデータをキャストする必要があるかもしれません。それらに対して警告するために、不安定なバージョンを含めました。(別の回答でステファンに特に感謝します。)

更新:加重相関を追加

于 2017-04-14T16:55:44.543 に答える
1

Excelの関数Forecastで使用される線形回帰関数を翻訳し、a、b、およびForecastを返すSQL関数を作成しました。完全な理論的説明は、FORECAST機能のExcelヘルプで確認できます。すべての最初に、テーブルデータ型XYFloatTypeを作成する必要があります。

 CREATE TYPE [dbo].[XYFloatType] 
AS TABLE(
[X] FLOAT,
[Y] FLOAT)

次に、次の関数を記述します。

    /*
-- =============================================
-- Author:      Me      :)
-- Create date: Today   :)
-- Description: (Copied Excel help): 
--Calculates, or predicts, a future value by using existing values. 
The predicted value is a y-value for a given x-value. 
The known values are existing x-values and y-values, and the new value is predicted by using linear regression. 
You can use this function to predict future sales, inventory requirements, or consumer trends.
-- =============================================
*/

CREATE FUNCTION dbo.FN_GetLinearRegressionForcast

(@PtXYData as XYFloatType READONLY ,@PnFuturePointint)
RETURNS @ABDData TABLE( a FLOAT, b FLOAT, Forecast FLOAT)
AS

BEGIN 
    DECLARE  @LnAvX Float
            ,@LnAvY Float
            ,@LnB Float
            ,@LnA Float
            ,@LnForeCast Float
    Select   @LnAvX = AVG([X])
            ,@LnAvY = AVG([Y])
    FROM @PtXYData;
    SELECT @LnB =  SUM ( ([X]-@LnAvX)*([Y]-@LnAvY) )  /  SUM (POWER([X]-@LnAvX,2))
    FROM @PtXYData;
    SET @LnA = @LnAvY - @LnB * @LnAvX;
    SET @LnForeCast = @LnA + @LnB * @PnFuturePoint;
    INSERT INTO @ABDData ([A],[B],[Forecast]) VALUES (@LnA,@LnB,@LnForeCast)
    RETURN 
END

/*
your tests: 

 (I used the same values that are in the excel help)
DECLARE @t XYFloatType 
INSERT @t VALUES(20,6),(28,7),(31,9),(38,15),(40,21)        -- x and y values
SELECT *, A+B*30 [Prueba]FROM dbo.FN_GetLinearRegressionForcast@t,30);
*/
于 2015-01-15T17:52:18.060 に答える
1

次の答えが、いくつかの解決策がどこから来ているのかを理解するのに役立つことを願っています。簡単な例で説明しますが、添字表記や行列の使い方を知っている限り、多くの変数への一般化は理論的には簡単です。3つの変数を超えるもののソリューションを実装するには、グラムシュミット(上記のColin Campbellの回答を参照)または別の行列反転アルゴリズムを使用します。

必要な関数はすべて分散、共分散、平均、合計などがSQLの集計関数であるため、ソリューションを簡単に実装できます。ロジスティックモデルのスコアの線形キャリブレーションを行うためにHIVEでこれを行いました。多くの利点の中で、1つは、スクリプト言語に出入りすることなく、HIVE内で完全に機能できることです。

データポイントがiによってインデックス付けされているデータ(x_1、x_2、y)のモデルは次のとおりです。

y(x_1、x_2)= m_1 * x_1 + m_2 * x_2 + c

モデルは「線形」に見えますが、そうである必要はありません。たとえば、x_2は、x_2 = Sinh(3 *(x_1)^ 2 +など)に自由パラメーターがない限り、x_1の任意の非線形関数にすることができます。 42)。x_2が「ちょうど」x_2であり、モデルが線形であっても、回帰問題はそうではありません。問題がL2エラーを最小化するようにパラメーターm_1、m_2、cを見つけることであると判断した場合にのみ、線形回帰の問題が発生します。

L2エラーはsum_i((y [i] --f(x_1 [i]、x_2 [i]))^ 2)です。これを3つのパラメーターで最小化すると(各パラメーター= 0で偏導関数を設定)、3つの未知数に対して3つの線形方程式が得られます。これらの方程式はパラメーターが線形であり(これが線形回帰になります)、分析的に解くことができます。単純なモデル(1つの変数、線形モデル、したがって2つのパラメーター)に対してこれを行うことは、簡単で有益です。エラーベクトル空間の非ユークリッド計量ノルムへの一般化は簡単で、対角線の特殊なケースは「重み」を使用することになります。

2つの変数でモデルに戻ります。

y = m_1 * x_1 + m_2 * x_2 + c

期待値を取る=>

= m_1 * + m_2 * + c(0)

ここで、共分散wrt x_1とx_2を取得し、cov(x、x)= var(x)を使用します。

cov(y、x_1)= m_1 * var(x_1)+ m_2 * covar(x_2、x_1)(1)

cov(y、x_2)= m_1 * covar(x_1、x_2)+ m_2 * var(x_2)(2)

これらは2つの未知数の2つの方程式であり、2X2行列を反転することで解くことができます。

行列形式の場合:...これを反転して...を生成できます。

det = var(x_1)* var(x_2)-covar(x_1、x_2)^ 2

(ああ、バーフ、「評判のポイント」とは一体何ですか?方程式を見たい場合は、ちょっと待ってください。)

いずれにせよ、m1とm2が閉じた形になっているので、cについて(0)を解くことができます。

上記の分析ソリューションをExcelのソルバーでチェックして、ガウスノイズのある二次関数を探しました。残差誤差は有効数字6桁に一致します。

SQLで離散フーリエ変換を約20行で実行したい場合は、私に連絡してください。

于 2015-09-19T07:04:32.013 に答える