一.线性回归

  线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为y = w’x+e,e为误差服从均值为0的正态分布。

回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析,这里我只是简单的实现一元线性回归。

线性回归模型经常用最小二乘逼近来拟合,但他们也可能用别的方法来拟合,比如用最小化“拟合缺陷”在一些其他规范里(比如最小绝对误差回归),或者在桥回归中最小化最小二乘损失函数的惩罚.相反,最小二乘逼近可以用来拟合那些非线性的模型.因此,尽管“最小二乘法”和“线性模型”是紧密相连的,但他们是不能划等号的。

二.最常用拟合方法——最小二乘法

  在我们研究两个变量(x, y)之间的相互关系时,通常可以得到一系列成对的数据(x1, y1),(x2, y2)… (xm , ym);将这些数据描绘在x -y直角坐标系中 若发现这些点在一条直线附近,可以令这条直线方程如(式1-1)。
y= e + wx(式1-1)
其中:w\e是任意实数
为建立这直线方程就要确定e和w,应用《最小二乘法原理》,将实测值Yi与利用(式1-1)计算值(y= be+ wx)的离差(yi-y)的平方和〔∑(yi - y)²〕最小为“优化判据”。

下面的例子是关于房子面积(x)和价格(y)的二元关系:
可以简单的用如下表达式表示:
                    y = wx+e
其中,y是房子的价格,x是对应房子的面积,e是误差。对于误差e,它不是一个定值,有一对y和x,就有一个e,e的值满足正态分布。

回归模型定义了输入和输出的关系。输入为现有信息,输出为预测。
一个预测问题在回归模型下的解决步骤为:
1.构造训练集;
2.学习,得到输入输出间的关系;
3.预测,通过学习得到的关系预测输出。

1.构造训练集;

先将定义的变量列举出来

 private final int frame_width = 800,frame_height = 500;
   MyJFrame jf;
   JLabel jl_input_house_size,jl_predict_house_price,jl_input_real_price,jl_equation,jl_flit_pic;
   JTextField input_house_size,predict_house_price,input_real_price,equation;
   Graphics g;

   JButton bt_get_price,bt_renew_price;   //按钮:输入完毕,更新价格

   DataSet_self extra_housemap=null,housemap =null;//数据准备

   //用于最小二乘法求斜率slope,截距intercept的准备数据
   private double intercept = 0.0 ;  //截距
   private double slope = 0.0 ;  //斜率
   double  sum_house_size,sum_house_price;		//面积、价格总和
   double average_size,average_price;	//面积、价格平均值
   double slope_up = 0,slope_down = 0; //求斜率的上下两个分式的值
   int number; //数据个数,

   //将数据存到这两个数组里面
   double[] house_price = new double[1000];
   double[] house_size = new double[1000];

   //格式化数据的小数点位数
   DecimalFormat df =new DecimalFormat("#.00");

   //继承JFrame的一个类,里面重写paint()方法
   class MyJFrame extends JFrame {
      public void paint(Graphics g)
      {
         super.paint(g);
         drawpic(house_price,house_size);
      }
   }

1)将(房子面积,房子价格)这个二元组存到哈希表中(数组什么的也可以,感觉哈希表没必要)

 private void initData()
   {
      if(housemap==null)
      {
         housemap = new DataSet_self();
         housemap.addData(50, 100);
         housemap.addData(55, 120);
         housemap.addData(60, 130);
         housemap.addData(62, 140);
         housemap.addData(68, 150);
         housemap.addData(75, 190);
         housemap.addData(150, 400);
         housemap.addData(90, 250);
         housemap.addData(100, 280);
         housemap.addData(110, 310);
         housemap.addData(120, 370);
      }
   }

2.学习,得到输入输出间的关系;

1)关键是计算出y= e + wx 中的相关量,w和e
其中b1是斜率,t是自变量,y是因变量
通过上式计算出出斜率w,在将x和y的平均值代入表达式,即可求出截距e的值。
具体来说就是处理一下数据,求出相应的量,那么就可以预测出表达式了。

2)求斜率w和截距e

 //将基础数据存放到两个数组里面,并求出求斜率slope需要的x,y变量的总和
   private void get_data()
   {
   //因为我用的是哈希表,这里是哈希表遍历的步骤,将数据取出来存到数组里面,方便后续画图。
      Set<Double> sets = housemap.keySet();
      Iterator<Double> iterator = sets.iterator();
      while(iterator.hasNext())
      {
         Double house_key = iterator.next();
         House_data house_object = housemap.get(house_key);
         double house_size = house_object.getHouse_size();
         double house_price = house_object.getHouse_price();
         this.house_price[number] = house_price;
         this.house_size[number] = house_size;
         number++;

         sum_house_size +=house_size;
         sum_house_price +=house_price;
      }
   }

   //求出这批数据的平均值
   private void seek_data(){
      average_size = sum_house_size/number;
      average_price = sum_house_price/number;

      for(int i = 0;i<number;i++)
      {
         slope_up +=(house_size[i]-average_size)*(house_price[i]-average_price);
         slope_down +=(house_size[i]-average_size)*(house_size[i]-average_size);
      }
   }
   //求回归方程的斜率,截距
   private void seek_slope_intercept() {
      if(slope_up!=0&&slope_down!=0)
      {
         slope = slope_up/slope_down;
      }
      intercept = average_price-average_size*slope;
   }

至此,就求出了截距和斜率。

3.预测,通过学习得到的关系预测输出。

   //预测数据
   public double predict(double x){
      return  intercept+slope*x;
   }

利用求出的斜率、截距返回就可,不过可以适当的进行误差分析…这里不进行阐述。当然,我设置了更新数据的功能,即将新输入的数据,作为样本,来改进自己的回归方程。

三.数据可视化

当然这只是一个简单的数据可视化。即将(面积,价格)的二元关系在面板上静态的呈现,同时,也做了一些其他数据呈现的东西,以及交互的东西,效果看图:
在这里插入图片描述
下面是画图的函数:

//画出图形
   private  void drawpic(double[] house_price,double[] house_size)
   {
      //画出框架
      g.setColor(Color.black);
      if(house_price!=null){
      g.drawLine(280,400,700,400);
      g.drawLine(280,400,280,20);
      g.setColor(Color.RED);}
      for (int i = 0;i<number;i++)
      {
         g.fillOval((int)house_size[i]+280,frame_height-(int)house_price[i],8, 8);
      }
      int y1 = (int)predict(0);
      int y2 = (int)predict(400);
      g.setColor(Color.green);
      g.drawLine(280,frame_height-y1,680, frame_height-y2);
   }

附上源码:
https://github.com/Ysupreme/IDEA-rep下载

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐