1. 程式人生 > >邏輯迴歸與梯度下降

邏輯迴歸與梯度下降

Logistic迴歸為概率型非線性迴歸模型,是研究二分類觀察結果與一些影響因素之間關係的一種

變數分析方法。通常的問題是,研究某些因素條件下某個結果是否發生,比如醫學中根據病人的一些症狀來判斷它是

否患有某種病。

在講解Logistic迴歸理論之前,我們先從LR分類器說起。LR分類器,即Logistic Regression Classifier。

在分類情形下,經過學習後的LR分類器是一組權值,當測試樣本的資料輸入時,這組權值與測試數

據按照線性加和得到

           

這裡是每個樣本的個特徵。之後按照Sigmoid函式(又稱為Logistic函式)的形式求出

           

由於Sigmoid函式的定義域為,值域為,因此最基本的LR分類器適合對兩類目標進行分類。

所以Logistic迴歸最關鍵的問題就是研究如何求得這組權值。此問題用極大似然估計來做。

下面正式地來講Logistic迴歸模型

考慮具有個獨立變數的向量,設條件慨率為根據觀測量相對於某事件發生

的概率。那麼Logistic迴歸模型可以表示為

           

其中那麼在條件下不發生的概率為

           

所以事件發生與不發生的概率之比為

           

這個比值稱為事件的發生比(the odds of experiencing an event),簡記為odds

可以看出Logistic迴歸都是圍繞一個Logistic函式來展開的。接下來就講如何用極大似然估計求分類器的引數。

假設有個觀測樣本,觀測值分別為,設為給定條件下得到的概率,

同樣地,的概率為,所以得到一個觀測值的概率為

因為各個觀測樣本之間相互獨立,那麼它們的聯合分佈為各邊緣分佈的乘積。得到似然函式為

                                         

然後我們的目標是求出使這一似然函式的值最大的引數估計,最大似然估計就是求出引數,使

取得最大值,對函式取對數得到

            

現在求向量,使得最大,其中

這裡介紹一種方法,叫做梯度下降法

(求區域性極小值),當然相對還有梯度上升(求區域性極大值)。

對上述的似然函式求偏導後得到

            

由於是求區域性極大值,所以根據梯度上升法,有

                    

根據上述公式,只需初始化向量全為零,或者隨機值,迭代到指定精度為止。

現在就來用C++程式設計實現Logistic迴歸的梯度上升演算法。首先要對訓練資料進行處理,假設訓練資料如下

訓練資料:TrainData.txt

1 0 0 1 0 1
0 0 1 2 0 0
1 0 0 1 1 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 1 0 1 0
0 0 1 2 1 0
1 0 0 0 0 0
0 0 1 0 1 0
1 0 1 0 0 0
0 0 1 0 1 0
0 0 1 0 0 0
0 0 1 0 1 0
1 0 0 1 0 0
1 0 0 0 1 0
2 0 0 0 1 0
1 0 0 2 1 0
2 0 0 0 1 0
2 0 1 0 0 0
0 0 1 0 1 0
0 0 1 2 0 0
0 0 0 0 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 2 1 0
1 0 1 0 0 0
0 0 1 0 0 0
0 0 0 2 0 0
1 0 0 0 1 0
2 0 1 0 0 0
2 0 1 1 1 0
1 0 1 1 0 0
1 0 1 2 0 0
1 0 0 1 1 0
0 0 0 0 1 0
1 1 0 0 1 0
1 0 1 2 1 0
0 0 0 0 1 0
0 0 1 0 0 0
1 0 1 1 1 0
1 0 1 0 1 0
2 0 1 2 0 0
0 0 1 2 1 0
0 0 1 0 1 0
2 0 1 0 1 0
0 0 1 0 1 0
1 0 0 0 0 0
1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 2 1 0
0 1 1 0 0 0
0 1 0 0 1 0
2 1 0 0 0 0
2 1 0 0 0 0
1 1 0 2 0 0
1 1 0 0 0 1
0 1 0 0 0 0
2 1 0 0 1 0
0 1 0 0 1 0
2 1 0 2 1 0
2 1 0 2 1 0
1 1 0 2 1 0
0 1 0 0 0 1
2 1 1 0 1 0
2 1 0 1 1 0
1 1 0 0 0 1
2 1 0 0 0 0
1 1 0 0 1 0
1 1 0 0 0 0
2 1 0 1 1 0
1 1 0 0 1 0
1 0 1 1 0 1
2 1 0 1 1 0
0 1 0 0 1 0
1 0 1 0 0 0
0 0 1 0 0 1
1 0 0 0 0 0
0 0 0 2 1 0
1 0 1 2 0 1
1 0 0 1 1 0
2 0 1 2 1 0
2 0 0 0 1 0
1 0 0 1 1 0
1 0 1 0 1 0
0 0 1 0 0 0
1 0 0 2 1 0
2 0 1 1 1 0
0 0 1 0 1 0
0 0 0 0 1 0
2 0 0 1 0 1
0 0 1 0 0 0
0 0 0 0 0 0
1 0 1 1 1 1
2 0 1 0 1 0
0 0 0 0 0 0
1 0 1 0 1 0
0 0 0 0 1 0
0 0 0 2 0 0
0 0 0 0 0 0
0 0 1 2 0 0
0 0 1 0 1 0
0 0 1 0 0 1
0 0 0 2 1 0
1 0 1 1 1 0
1 0 0 1 1 0
0 0 1 0 1 0
1 0 0 0 0 0
1 0 1 0 1 0
2 0 0 0 1 0
1 0 0 0 1 0
2 0 0 1 1 0
0 0 1 2 1 0
1 0 1 2 0 0
0 0 1 2 1 0
1 0 0 0 0 0
0 0 1 0 1 0
0 0 0 1 1 0
1 0 0 0 1 0
2 0 0 1 1 0
1 0 0 1 1 0
1 0 1 0 0 0
1 1 0 1 1 0
2 1 0 0 1 0
0 1 0 0 0 0
1 1 0 1 0 1
1 1 0 2 1 0
0 1 0 0 0 0
1 1 0 2 0 0
0 1 0 0 1 0
1 1 0 0 1 1
1 1 0 2 1 0
1 0 0 2 1 0
2 1 1 1 1 0
0 1 0 0 1 0
0 1 0 0 1 0
2 1 0 0 0 1
1 1 0 2 1 0
1 1 0 0 1 0
1 1 1 0 0 0
2 1 0 2 1 0
2 1 1 1 0 0
0 1 0 0 1 0
1 1 0 2 1 0
0 1 0 0 1 0
1 1 0 1 1 0
0 1 0 0 1 0
0 1 0 0 0 0
1 1 0 0 0 0
1 1 0 2 1 0
1 1 0 0 0 0
0 1 1 2 0 0
2 1 0 0 1 0
2 0 1 0 0 1
0 0 1 0 1 0
1 0 1 0 0 0
0 0 1 2 1 0
0 0 1 0 0 0
1 0 1 0 1 0
0 0 1 0 1 0
0 0 1 0 1 0
1 0 1 0 1 0
0 0 0 0 0 1
0 0 1 2 1 0
0 0 1 0 1 0
0 0 1 0 1 0
0 0 1 0 0 0
0 0 1 0 0 1
0 0 1 2 1 0
2 0 1 2 1 0
0 0 1 0 1 0
0 0 1 0 1 0
0 0 1 0 1 0
1 0 0 0 0 0
2 0 1 1 1 0
0 0 1 0 0 1
1 0 1 0 0 0
1 0 1 1 1 0
1 0 1 1 0 0
0 0 1 0 0 0
1 0 1 1 1 0
1 0 1 2 0 0
2 0 0 0 1 0
0 0 1 0 0 1
0 0 1 0 1 0
0 0 1 0 1 0
1 0 1 0 0 0
0 0 1 0 0 0
2 0 1 1 0 0
0 0 1 2 0 0
1 0 0 1 1 1
0 0 0 0 1 0
0 0 0 0 0 1
0 0 1 0 1 0
2 0 1 2 1 0
1 0 0 1 0 0
0 0 1 0 0 0
2 0 0 1 1 1
0 0 1 0 0 0
0 0 1 0 1 0
2 0 1 0 1 0
0 0 1 0 1 0
2 0 0 0 1 0
1 0 1 0 1 0
1 0 0 0 1 0
0 0 1 0 0 1
2 0 0 0 0 0
2 0 0 1 1 0
0 0 1 0 1 0
0 0 0 0 1 0
2 0 1 0 0 0
1 0 1 0 1 0
0 0 0 0 1 0
1 0 1 0 1 0
0 0 1 0 0 0
1 0 1 0 1 0
1 0 1 0 1 0
1 0 1 0 1 0
0 0 1 2 0 0
2 0 1 0 1 1
0 0 1 0 1 0
0 0 1 2 1 0
0 0 0 0 0 0
0 0 1 0 1 0
1 0 1 0 1 0
0 0 1 0 1 0
1 0 1 0 0 0
0 0 1 0 1 0
0 0 1 0 0 0
1 0 1 0 0 0
0 0 1 0 1 0
0 0 1 0 1 0
1 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 1 0
1 0 1 1 1 0
0 0 0 2 0 0
0 0 1 0 1 0
0 0 1 0 1 0
0 0 1 0 1 0
1 0 0 1 1 0
2 0 0 0 1 0
1 0 0 0 0 0
2 0 0 2 1 0
0 0 1 2 1 0
1 0 1 0 0 1
0 0 1 2 1 0
0 0 1 2 1 0
0 0 1 0 1 0
1 0 1 2 1 0
0 0 0 2 0 0
1 0 0 0 0 0
0 0 0 2 1 0
0 0 1 0 1 0
2 0 0 0 1 0
1 0 0 0 0 0
1 0 0 1 1 0
1 0 1 1 1 0
1 0 1 0 1 1
0 0 1 0 1 0
1 1 0 2 1 0
1 1 0 1 0 0
2 1 0 2 1 0
1 1 1 0 0 0
0 1 1 0 0 0
0 1 1 0 0 1
0 1 0 0 1 0
1 1 1 0 0 0
1 1 1 0 1 0
0 1 0 0 1 0
0 1 1 0 0 1
1 1 1 1 1 0
1 1 0 2 1 0
0 1 0 2 0 0
1 1 0 2 1 0
0 0 1 2 1 0
2 1 1 1 1 0
0 1 0 0 1 0
0 0 1 0 1 0
2 1 0 1 1 0
0 1 0 0 1 0
1 1 0 0 0 0
1 1 0 0 1 0
0 1 0 0 0 0
0 1 1 0 0 0
2 1 0 0 1 0
2 1 0 0 0 0
1 1 0 0 1 0
2 1 0 1 1 0

上面訓練資料中,每一行代表一組訓練資料,每組有7個數組,第1個數字代表ID,可以忽略之,2~6代表這組訓

練資料的特徵輸入,第7個數字代表輸出,為0或者1。每個資料之間用一個空格隔開。

首先我們來研究如何一行一行讀取文字,在C++中,讀取文字的一行用getline()函式。

getline()函式表示讀取文字的一行,返回的是讀取的位元組數,如果讀取失敗則返回-1。用法如下:

#include <iostream>
#include <string.h>
#include <fstream>
#include <string>
#include <stdio.h>
 
using namespace std;
 
int main()
{
    string filename = "data.in";
    ifstream file(filename.c_str());
    char s[1024];
    if(file.is_open())
    {
        while(file.getline(s,1024))
        {
            int x,y,z;
            sscanf(s,"%d %d %d",&x,&y,&z);
            cout<<x<<" "<<y<<" "<<z<<endl;
        }
    }
    return 0;
}


拿到每一行後,可以把它們提取出來,進行系統輸入。 Logistic迴歸的梯度上升演算法實現如下

程式碼:

#include <iostream>
#include <string.h>
#include <fstream>
#include <stdio.h>
#include <math.h>
#include <vector>
 
#define Type double
#define Vector vector
using namespace std;
 
struct Data
{
    Vector<Type> x;
    Type y;
};
 
void PreProcessData(Vector<Data>& data, string path)
{
    string filename = path;
    ifstream file(filename.c_str());
    char s[1024];
    if(file.is_open())
    {
        while(file.getline(s, 1024))
        {
            Data tmp;
            Type x1, x2, x3, x4, x5, x6, x7;
            sscanf(s,"%lf %lf %lf %lf %lf %lf %lf", &x1, &x2, &x3, &x4, &x5, &x6, &x7);
            tmp.x.push_back(1);
            tmp.x.push_back(x2);
            tmp.x.push_back(x3);
            tmp.x.push_back(x4);
            tmp.x.push_back(x5);
            tmp.x.push_back(x6);
            tmp.y = x7;
            data.push_back(tmp);
        }
    }
}
 
void Init(Vector<Data> &data, Vector<Type> &w)
{
    w.clear();
    data.clear();
    PreProcessData(data, "TrainData.txt");
    for(int i = 0; i < data[0].x.size(); i++)
        w.push_back(0);
}
 
Type WX(const Data& data, const Vector<Type>& w)
{
    Type ans = 0;
    for(int i = 0; i < w.size(); i++)
        ans += w[i] * data.x[i];
    return ans;
}
 
Type Sigmoid(const Data& data, const Vector<Type>& w)
{
    Type x = WX(data, w);
    Type ans = exp(x) / (1 + exp(x));
    return ans;
}
 
Type Lw(const Vector<Data>& data, Vector<Type> w)
{
    Type ans = 0;
    for(int i = 0; i < data.size(); i++)
    {
        Type x = WX(data[i], w);
        ans += data[i].y * x - log(1 + exp(x));
    }
    return ans;
}
 
void Gradient(const Vector<Data>& data, Vector<Type> &w, Type alpha)
{
    for(int i = 0; i < w.size(); i++)
    {
        Type tmp = 0;
        for(int j = 0; j < data.size(); j++)
            tmp += alpha * data[j].x[i] * (data[j].y - Sigmoid(data[j], w));
        w[i] += tmp;
    }
}
 
void Display(int cnt, Type objLw, Type newLw, Vector<Type> w)
{
    cout<<"第"<<cnt<<"次迭代:  ojLw = "<<objLw<<"  兩次迭代的目標差為: "<<(newLw - objLw)<<endl;
    cout<<"引數w為: ";
    for(int i = 0; i < w.size(); i++)
        cout<<w[i]<<" ";
    cout<<endl;
    cout<<endl;
}
 
void Logistic(const Vector<Data>& data, Vector<Type> &w)
{
    int cnt = 0;
    Type alpha = 0.1;
    Type delta = 0.00001;
    Type objLw = Lw(data, w);
    Gradient(data, w, alpha);
    Type newLw = Lw(data, w);
    while(fabs(newLw - objLw) > delta)
    {
        objLw = newLw;
        Gradient(data, w, alpha);
        newLw = Lw(data, w);
        cnt++;
        Display(cnt,objLw,newLw, w);
    }
}
 
void Separator(Vector<Type> w)
{
    Vector<Data> data;
    PreProcessData(data, "TestData.txt");
    cout<<"預測分類結果:"<<endl;
    for(int i = 0; i < data.size(); i++)
    {
        Type p0 = 0;
        Type p1 = 0;
        Type x = WX(data[i], w);
        p1 = exp(x) / (1 + exp(x));
        p0 = 1 - p1;
        cout<<"例項: ";
        for(int j = 0; j < data[i].x.size(); j++)
            cout<<data[i].x[j]<<" ";
        cout<<"所屬類別為:";
        if(p1 >= p0) cout<<1<<endl;
        else cout<<0<<endl;
    }
}
 
int main()
{
    Vector<Type> w;
    Vector<Data> data;
 
    Init(data, w);
    Logistic(data, w);
    Separator(w);
    return 0;
}

測試資料:TestData.txt

10009 1 0 0 1 0 1
10025 0 0 1 2 0 0
20035 0 0 1 0 0 1
20053 1 0 0 0 0 0
30627 1 0 1 2 0 0
30648 2 0 0 0 1 0

相關推薦

邏輯迴歸梯度下降

Logistic迴歸為概率型非線性迴歸模型,是研究二分類觀察結果與一些影響因素之間關係的一種 多變數分析方法。通常的問題是,研究某些因素條件下某個結果是否發生,比如醫學中根據病人的一些症狀來判斷它是 否患有某種病。 在講解Logistic迴歸理論之前,我們先從LR分類器說

邏輯迴歸梯度下降

轉載自:http://www.cnblogs.com/yysblog/p/3268508.html 一、邏輯迴歸 1) Classification(分類) 分類問題舉例: 郵件:垃圾郵件/非垃圾郵件?線上交易:是否欺詐(是/否)?腫瘤:惡性/良性? 以上問題可以

斯坦福CS229機器學習課程筆記一:線性迴歸梯度下降演算法

機器學習三要素 機器學習的三要素為:模型、策略、演算法。 模型:就是所要學習的條件概率分佈或決策函式。線性迴歸模型 策略:按照什麼樣的準則學習或選擇最優的模型。最小化均方誤差,即所謂的 least-squares(在spss裡線性迴歸對應的模組就叫OLS即Ordinary Least Squares):

吳恩達深度學習deeplearning.ai-Week2課後作業-Logistic迴歸梯度下降向量化

一、deeplearning-assignment 這篇文章會幫助構建一個用來識別貓的邏輯迴歸分類器。通過這個作業能夠知道如何進行神經網路學習方面的工作,指導你如何用神經網路的思維方式做到這些,同樣也會加深你對深度學習的認識。 儘量不要在程式碼中出現for迴圈,可以用nu

邏輯迴歸梯度下降

  1. 概率 1.1 定義   1.2 範圍   1.3 計算方法 1.3.1 根據個人置信 1.3.2 根據歷史資料 1.3.3 根據模擬資料 1.4 條件概率 2. 2.1 &

線性迴歸梯度下降

線性迴歸(Linear Regression) 從這篇文章開始,主要介紹機器學習的一些列基本演算法,本文介紹線性迴歸問題,以及利用最小均方和梯度下降解決線性迴歸問題。 (以下內容是根據斯坦福大學ng教授的機器學習公開課總結的內容) 監督學習:即訓練資料中既包含了輸入資

第一個機器學習演算法:線性迴歸梯度下降

# 第一個機器學習演算法:線性迴歸與梯度下降 ## 符號解釋 * $x^{(i)}$,$y^{(i)}$:某個訓練樣本 * $m$:樣本總數量 * $h_{\theta}$:假設函式 ## Linear regression(線性迴歸) ### 如何獲得一個線性迴歸模型? * 將**訓練資料**放入

機器學習(二):理解線性迴歸梯度下降並做簡單預測

# 預測從瞎猜開始 按[上一篇文章](https://mp.weixin.qq.com/s/-KsbtgOc3C3ry-8P5f8K-Q)所說,機器學習是應用數學方法在資料中發現規律的過程。既然數學是對現實世界的解釋,那麼我們迴歸現實世界,做一些對照的想象。 想象我們面前有一塊塑料泡沫做的白板,白板上

線性迴歸梯度下降講解程式碼

本文也是根據吳恩達機器學習課程作業的答案。 迴歸:預測值是連續的; 分類:預測值是離散的; 建模誤差:預測值與實際值之間的差距; 目標:選擇模型引數,使得建模誤差的平方和能夠最小,即代價函式最小; 代價函式:選擇平方誤差函式,是解決迴歸問題最常用的手段;代價函式是幫助我們選擇最優

線性迴歸梯度下降演算法 tensorflow

舉個栗子 考慮一個二手房交易記錄資料集. 已知房屋面積,臥室數量和交易價格: 根據這個資料集,要求我們估算當前某個給定房屋價格. 我們應該怎麼做? 線性迴歸 迴歸就是根據已知資料來預測另一個數值型資料的目標值. 假設特徵和結果滿足線性關係: h(x

【機器學習】1 監督學習應用梯度下降

例如 tla ges 機器 fprintf lns 找到 輸入 style 監督學習 簡單來說監督學習模型如圖所示 其中 x是輸入變量 又叫特征向量 y是輸出變量 又叫目標向量 通常的我們用(x,y)表示一個樣本 而第i個樣本 用(x(i),y(i))表示 h是輸出函

通過實例詳解隨機梯度梯度下降

lns 情況 line strong spa www lin span 理論 一、梯度下降、隨機梯度下降、批量梯度下降 梯度下降:梯度下降中,對於θ 的更新,所有的樣本都有貢獻,也就是參與調整θ 。其計算得到的是一個標準梯度。因而理論上來說一次更新的幅度是比較大的。如果樣

機器學習:線性回歸——理論代碼實現(基於正規方程梯度下降

overfit 返回 pen ear 隨機梯度 是否 很大的 建模 回歸 一 線性模型 給定由n個屬性描述的列向量\(f(\mathbf{x})={(x^{(1)};x^{(2)};...;x^{(n)})}\),其中 \(x^{(j)}\)是\(\textbf{x}\)

【Mark Schmidt課件】機器學習資料探勘——數值優化梯度下降

本課件主要包括以下內容: 優化簡介 上次課程回顧:線性迴歸 大規模最小二乘 尋找區域性最小值的梯度下降法 二維梯度下降 存在奇異點的最小二乘 魯棒迴歸 基於L1-範數的迴歸 L1-範數的平滑近似

機器學習入門 線性迴歸梯度下降

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

反向傳播梯度下降的基本概念

反向傳播和梯度下降這兩個詞,第一眼看上去似懂非懂,不明覺厲。這兩個概念是整個神經網路中的重要組成部分,是和誤差函式/損失函式的概念分不開的。 神經網路訓練的最基本的思想就是:先“蒙”一個結果,我們叫預測結果h,看看這個預測結果和事先標記好的訓練集中的真實結果y之間的差距,然後調整策略,再試一次,這一次就不是

機器學習--邏輯迴歸softmax

1. 簡介 邏輯迴歸和Softmax迴歸是兩個基礎的分類模型,前者主要處理二分類問題,而後者處理多分類問題,但事實上Softmax迴歸就是邏輯迴歸的一般形式。 2.邏輯迴歸模型    sigmoid 想了解Logistic迴歸,我們必須先看一看

tensorflow的歸一化梯度下降

程式碼: # coding=utf-8 # By author MZ import numpy as np from sklearn.datasets import load_boston import tensorflow as tf from sklearn.preproces

【CS229】代價函式梯度下降

一些寫法約定: x x x: 輸入變數,特徵

機器學習4:邏輯迴歸線性迴歸

邏輯迴歸與線性迴歸求解過程: 總體來說,迴歸過程都分三步: 1、Model 2、Loss Fuction 3、Gradient Decent 分析: 1、Model:線性迴歸中,模型為線性方程,取值範圍無窮大;邏輯迴歸中,通過sigmod函式函式將線性方程z轉化成概率(