使用存储在数据库中的数据查找线性分类器

时间:2013-03-30 09:38:34

标签: sql database

我的任务如下:我有一个包含X, Y, Class列的表格  其中x坐标在笛卡尔坐标系中,  笛卡尔坐标系中的y坐标  和一个点的类别,例如1级,2级)。  我需要找到一条划分平面的线,使得单独的类的点位于坐标系的两个独立部分中。这是我第一次使用线性分类器。我想知道如何使用一个select查询来实现这一点 - 允许子查询。

1 个答案:

答案 0 :(得分:1)

我的第一反应是,这不是一个适合SQL的问题,你应该查找统计/数据分析软件。 “最佳”这样的线由支持向量机(SVM)提供,您可以查找它。

但是,如果你有很多时间或很少的积分,你可以试试暴力法。也就是说,查看可能的行列表,看看它们分裂的程度。

因此,假设一条线具有等式y = mx + b。这是对一堆具有不同斜率的线的测试。您可以通过y - mx + b是正还是负来测试线的边。然后,您可以为每一侧和每个类别聚合,并使用一些逻辑来选择类别的一面。

为此,我使用的是SQL Server语法:

with nums as (  -- get a bunch of nums
      select row_number() over (order by null) as n
      from information_schema.columns c
     ),
    m as (
     select n - 10 as m  -- from -10 to 10
     from nums
     where n <= 21
    ),
    b as (
     select n - 10 as b  -- from -10 to 10
     from nums
     where n <= 21
    )
    lines as (
     select m, b
     from m cross join b
    )
select m, b,
       (case when cat1_side1 > cat1_side2 then 'side1' else 'side2'
        end) as cat1_side,
       (case when cat1_side1 > cat1_side2 then cat1_side1 else cat1_side2
        end) as cat1_correct,
      (case when cat1_side1 > cat1_side2 then 'side2' else 'side1'
       end) as cat2_side,  -- force cat2 to the other side
      (case when cat1_side1 > cat1_side2 then cat2_side2 else cat2_side1
       end) as cat2_correct
from (select l.m, l.b, 
             sum(case when p.category = 'cat1' and p.y - (p.x*l.m + l.b) < 0
                      then 1 else 0
                 end) as cat1_side1_cnt,
             sum(case when p.category = 'cat1' and p.y - (p.x*l.m + l.b) > 0
                      then 1 else 0
                 end) as cat1_side2_cnt,
             sum(case when p.category = 'cat2' and p.y - (p.x*l.m + l.b) < 0
                      then 1 else 0
                 end) as cat2_side1_cnt,
             sum(case when p.category = 'cat2' and p.y - (p.x*l.m + l.b) > 0
                      then 1 else 0
                 end) as cat2_side2_cnt,
      from points p cross join
           lines l
      group by l.m, l.b, p.category
     ) lp
order by (cat1_correct + cat2_correct) desc

请注意,此代码选择category1的一侧,而这反过来会强制另一方为类别2.您不能为每个选择最佳的一面,因为您的所有数据点可能位于线。

此外,这对垂直线不起作用,但它很接近。

将这些放在一起时,我说这是解决此问题的最佳方法。但是,对于少量数据点,它实际上可能工作得很好。