sql >> データベース >  >> RDS >> Sqlserver

SQL Server に線形回帰関数はありますか?

    私の知る限り、何もありません。ただし、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 を使用しました 明確にするための声明。別の方法として、代わりにサブクエリを使用できます。データに対して精度が十分に高くないと、数値の安定性が急速に低下する可能性があるため、テーブルで使用されるデータ型の精度に注意してください。

    編集: (コメントの 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
      

    編集 2 (センタリングのみではなく) データを標準化し、STDEV を置き換えることにより、数値の安定性を向上させます 数値安定性の問題 .私には、現在の実装が安定性と複雑さの間の最良のトレードオフのように思えます。標準偏差を数値的に安定したオンライン アルゴリズムに置き換えることで安定性を向上させることができますが、実装がかなり複雑になります (そして速度が低下します)。同様に、たとえばを使用した実装。 SUM の Kahan(-Babuška-Neumaier) 補正 および AVG 限られたテストではパフォーマンスが多少向上しているように見えますが、クエリははるかに複雑になります。そして、T-SQL が SUM をどのように実装するかを知らない限り および AVG (例えば、すでにペアごとの合計を使用している可能性があります)、そのような変更が常に精度を向上させることを保証することはできません.



    1. HibernateアノテーションなしでPostgreSQLのテキストタイプのJPAアノテーションを修正する

    2. ADFS 2.0を使用して、SQL Serverに対して特定のユーザーを認証できますか?

    3. リアルタイム通信のためにFirebaseをPHPと統合する

    4. MySQLのJSON_SET()とJSON_INSERT()とJSON_REPLACE():違いは何ですか?