SQL Server 2005/2008には Oracleの線形回帰関数 と同様の線形回帰関数がありますか?
私の知る限りではありません。ただし、1つを書くのは非常に簡単です。以下は、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
ステートメントを使用しました。代わりに、代わりにサブクエリを使用できます。データに対して精度が十分に高くない場合、数値の安定性がすぐに低下する可能性があるため、テーブルで使用されるデータ型の精度に注意してください。
EDIT:(コメントのR2のような追加の統計に関するピーターの質問に答えて)
同じ手法を使用して、追加の統計を簡単に計算できます。以下は、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
を置き換えることで数値の安定性を向上させます 数値の安定性の問題 。私にとって、現在の実装は、安定性と複雑さの間の最良のトレードオフのようです。標準偏差を数値的に安定したオンラインアルゴリズムに置き換えることで安定性を向上させることはできますが、これにより実装が大幅に複雑になります(そして速度が低下します)。同様に、たとえば、 SUM
およびAVG
に対するKahan(-Babuška-Neumaier)の補正は、限られたテストでは適度に優れているように見えますが、クエリがはるかに複雑になります。 T-SQLがSUM
とAVG
を実装する方法がわからない限り(たとえば、すでにペアワイズ合計を使用している可能性があります)、そのような変更によって常に精度が向上することを保証できません。
これは、次の式を使用する 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
実際に、グラム・シュミットの直交化を使用してSQLルーチンを作成しました。それ、および他の機械学習と予測ルーチンは sqldatamine.blogspot.com で入手できます。
Brad Larsonの提案で、ユーザーをブログに直接誘導するのではなく、ここにコードを追加しました。これは、Excelのlinest関数と同じ結果になります。私の主な情報源はHastie、Tibshirni、FriedmanによるElements of Statistical 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
SQL Serverには線形回帰関数はありません。しかし、データポイントのペアx、y間の単純な線形回帰(Y '= bX + A)を計算するには、相関係数、決定係数(R ^ 2)、標準誤差推定(標準偏差)の計算を含みます。以下をせよ:
テーブルの場合regression_data
数値列x
およびy
付き:
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
@ icc97の回答に追加するために、勾配と切片に加重バージョンを含めました。値がすべて一定の場合、勾配はNULLになります(適切な設定でSET ARITHABORT OFF; SET ANSI_WARNINGS OFF;
)であり、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,
count(*) as n
from d where x is not null and y is not null group by segment
ここで、wは重量です。結果を確認するために、Rに対してこれをダブルチェックしました。データをsomedatasourceから浮動小数点にキャストする必要があるかもしれません。それらに対して警告するために不安定なバージョンを含めました。 (別の答えでステファンに感謝します。)
相関はデータポイントxとyの相関であり、予測ではないことに注意してください。
Excelの関数予測で使用される線形回帰関数を翻訳し、a、b、および予測を返すSQL関数を作成しました。詳細な説明は、ExcelのFORECAST関数のヘルプで確認できます。はじめに、テーブルデータタイプXYFloatTypeを作成する必要があります。
CREATE TYPE [dbo].[XYFloatType]
AS TABLE(
[X] FLOAT,
[Y] FLOAT)
次に、follow関数を記述します。
/*
-- =============================================
-- 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);
*/
これは、次のタイプのテーブルタイプを取る関数です:table(Y float、X double)はXYDoubleTypeと呼ばれ、線形関数が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
次の回答が、いくつかの解決策の出所を理解する助けになることを願っています。簡単な例で説明しますが、インデックス表記または行列の使用方法を知っている限り、多くの変数の一般化は理論的に簡単です。 3つの変数以外のソリューションを実装するには、グラムシュミット(上記のコリンキャンベルの回答を参照)または別の行列反転アルゴリズムを使用します。
必要なすべての関数は分散、共分散、平均、合計などなので、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_1の任意の非線形関数を使用できます。 x_2 = Sinh(3 *(x_1)^ 2 + 42)。 x_2が「ちょうど」x_2でモデルが線形である場合でも、回帰問題はそうではありません。問題がパラメーターm_1、m_2、cを見つけてL2エラーを最小化することであると判断した場合のみ、線形回帰問題が発生します。
L2エラーはsum_i((y [i]-f(x_1 [i]、x_2 [i]))^ 2)です。これを最小限に抑える3つのパラメーター(偏微分w.r.tを設定します。各パラメーター= 0)は、3つの未知数に対して3つの線形方程式を生成します。これらの方程式は、パラメータが線形であり(これが線形回帰の原因です)、分析的に解くことができます。単純なモデル(1つの変数、線形モデル、したがって2つのパラメーター)に対してこれを行うと、簡単で有益です。エラーベクトル空間での非ユークリッドメトリックノルムへの一般化は簡単です。対角線の特殊な場合は、「重み」を使用することになります。
2つの変数でモデルに戻ります。
y = m_1 * x_1 + m_2 * x_2 + c
期待値を取る=>
= m_1 * + m_2 * + c(0)
次に、共分散w.r.tを取ります。 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のソルバーでチェックして、ガウスノイズのある2次曲線を探しました。残差は6桁の有効数字に一致しています。
SQLで離散フーリエ変換を約20行で実行する場合は、私に連絡してください。