码迷,mamicode.com
首页 > 其他好文 > 详细

机器学习之logistic回归与分类

时间:2015-08-08 18:24:00      阅读:1365      评论:0      收藏:0      [点我收藏+]

标签:机器学习   数据   logistic分类   

logistic回归与分类是一种简单的分类算法。在分类的过程中只需要找到一个划分不同类的权重向量即可,对新的数据只需要乘上这个向量并比较就可以得到分类。比如下图的二分类问题:
技术分享
每个样本点可以看成包含两个特征(x1,x2),现在需要把他们分开,如果这是训练集,他们本身属于哪一个类是已知的,比如说蓝色的属于0类,红色的属于1类,现在我们想通过这些数据建立一个分类标准可以将他们分开,这样再来了一个不知道类别的数据,我们看看这个标准就知道他是属于哪一类的。

像上面这个线性的,那么我们可以建立一个函数模型,假设有一个函数z=w1?x1+w2?x2可以将他们分开,也就是每一个样本(x1,x2)通过这个函数有一个z,当z大于某个值就认为属于第一类,否则属于第二类。那么我们知道,样本确定后(x1,x2)不能变了,那么我们想办法变化这个函数的权值系数(w1,w2)。这个简单的式子可以化简成x2=?k?x1+b的形式,看到这不是一元函数吗,只要有了适当的k和b就可以画出上面的分割线是不是。

下面的问题,如何找到w1与w2,因为我们的数据是已知属于哪一类的了,那么这样的话我们可以开始随机给一组w1与w2,然后将每个点(或者所有点)带到这个函数中,假设我们的z的阈值给的是100,那么带一个点(x1,x2)进去算,发现得到的z=50,划分到第一类,然而实际情况是第二类,划分错了,这样我们调整一下(w1,w2),再来划分下一个点,就这样一直下去直到(w1,w2)能很好的划分出这些数据为止。

Logistic寻找参数的过程就是这样,那么这里就有几个问题:
(1)关于阈值z=50的选择
为什么你选择50,不是100,200呢?我们知道当x1与x2的数值(范围)变化了之和,这个阈值会变化的。所以为了消除这个影响,我们将得到的z在进行一个映射,这个映射函数就是sigmod函数,函数的形式如下:

σ(z)=11+e?z

这个函数的特点就是无论给的输入z多大多小,输出的值都在0-1之间。这样对于所有二分类情况,我们就可以统一把阈值设置为0.5,一半一类一半另一类正好。那么输出的z(z还是通过上面的函数权值相乘而来)经过这个映射后就变化到0-1之间的一个值了,用一个图表示如下:
技术分享

可能会说,将数值映射到0-1之间的方式有很多,为什么单单选择这个呢?我感觉这和神经网络里面用sigmod函数作为映射关系差不多,在那里用这个函数的作用就在于这个函数求导后的值可以用自身表示出来,而这里将值转化到0-1以后,分类问题就好似概率问题了。

在logistic中,我们采用的是梯度上升(与下降类似)算法来更新权值,用误差函数对各个权值参数求导数。

?J(w)?w=?w12i=1m(hw(x)?y)2=(hw(x)?y)x(i)

那么w的更新如下:
w=w+?J(w)?w

关于详细原理可参考:梯度下降法

(2)关于适用的分类说明
logistic一般适用于简单线性的二分类问题,虽然sigmod的映射不是线性的,但是输入到sigmod的值确是由线性求和而来,并且这个求和占主要因素。在二分类里面,一般将分类问题转化为0-1分类的标签,加入要分类的样本的分类标签不是0-1,那么需要转化过来,因为sigmod函数出来的就是0-1之间的数字,要想有梯度,要想有反馈输出值必须在这个量级的才行。
这是二分类问题。那么logistic能不能多分类?可以,将多分类转化为所有的多个二分类问题,然后对样本,先依次进行二分类,最后举手表决哪个类最多就属于哪个类,这样就可以实现多分类了。

下面在matlab下试验logistic回归分类,包括二分类以及多分类。
首先是样本的选择,这个样本曾经在

聚类之详解FCM算法原理及应用

机器学习之实战朴素贝叶斯算法?

里面用过,是关于种子分类的,每个种子有7个特征,种子分为3类,共210个样本,样本下载地址:
http://archive.ics.uci.edu/ml/datasets/seeds#

将数据存为txt保存到matlab工作目录下。
先进行二分类,样本还是这个,不过将里面1,2类或者2,3类或者1,3类的数据提取出来,单单对这两个类分类。

%%  
% * Logistic方法用于回归分析与分类设计
% * 简单0-1两类分类
% 
%% 
clc
clear
close all
%% Load data
% * 数据预处理--这里因为只分两类情况,所以挑选出1,2类数据,
% 并将标签重新设置为0与1,方便sigmod函数应用 
data = importdata(‘data.txt‘);
index = find((data(:,8)==1)|(data(:,8)==2));
data = data(index,:);
data(:,8) = data(:,8) - 1;
%选择训练样本个数
num_train = 50;
%构造随机选择序列
choose = randperm(length(data));
train_data = data(choose(1:num_train),:);
label_train = train_data(:,end);
test_data = data(choose(num_train+1:end),:);
label_test = test_data(:,end);
data_D = size(train_data,2) - 1;
% initial ‘weights‘ para
weights = ones(1,data_D);
%% training data weights
% * 随机梯度上升算法-在线学习
for j = 1:100
    alpha = 0.1/j;
    for i = 1:length(train_data)
        data = train_data(i,1:end-1);
        h = 1.0/(1+exp(-(data*weights‘)));
        error = label_train(i) - h;
        weights = weights + (alpha * error * data);
    end
end
% * 整体梯度算法-批量/离线学习
% for j = 1:2000
%     alpha = 0.1/j;
% %     alpha = 0.001;
%     data = train_data(:,1:end-1);
%     h = 1./(1+exp(-(data*weights‘)));
%     error = label_train - h;
%     weights = weights + (alpha * data‘ * error)‘;
% end
%% test itself (the training data)
diff = zeros(2,length(train_data));
for i = 1:length(train_data)
    data = train_data(i,1:end-1);
    h = 1.0/(1+exp(-(data*weights‘)));
    %compare to every label
    for j = 1:2 
        diff(j,i) = abs((j-1)-h);
    end
end
[~,predict] = min(diff);
%show the result
figure;
plot(label_train+1,‘+‘)
hold on
plot(predict,‘or‘);
hold on 
plot(abs(predict‘-(label_train+1)));
axis([0,length(train_data),0,3])
accuracy = length(find(predict‘==(label_train+1)))/length(train_data);
title([‘predict Training Data and the accuracy is :‘,num2str(accuracy)]);
%% predict the testing data
diff = zeros(2,length(test_data));
for i = 1:length(test_data)
    data = test_data(i,1:end-1);
    h = 1.0/(1+exp(-(data*weights‘)));
    %compare to every label
    for j = 1:2 
        diff(j,i) = abs((j-1)-h);
    end
end
[~,predict] = min(diff);
% show the result
figure;
plot(label_test+1,‘+‘)
hold on
plot(predict,‘or‘);
hold on 
plot(abs(predict‘-(label_test+1)));
axis([0,length(test_data),0,3])
accuracy = length(find(predict‘==(label_test+1)))/length(test_data);
title([‘predict the testing data and the accuracy is :‘,num2str(accuracy)]);

一次结果如下:
这是对训练样本训练出参数后再回去看看它的准确率。
技术分享

这是测试样本的准确率。
技术分享

在程序里面可以看到,有尖锋的地方就是分错了的地方。对于样本训练得到参数w有两种方式,一种是批量的一种是单个的,也叫作离线学习与在线学习,对训练样本的选择以及参数的设定不同得到的结果都会不一样,可以试试。

下面进行多类问题的分类,多类分类就要将所有样本全部用上,这里其实一共就3类,不过也算是多类。代码如下:

%%  
% * Logistic方法用于回归分析与分类设计
% * 多类问题的分类
% 
%% 
clc
clear
close all
%% Load data
% * 数据预处理--这里因为只分两类情况,所以挑选出1,2类数据,
% 并将标签重新设置为01,方便sigmod函数应用 
data = importdata(‘data.txt‘);
%选择训练样本个数
num_train = 50;
%构造随机选择序列
choose = randperm(length(data));
train_data = data(choose(1:num_train),:);
label_train = train_data(:,end);
test_data = data(choose(num_train+1:end),:);
label_test = test_data(:,end);
data_D = size(train_data,2) - 1;
% initial ‘weights‘ para
% label number
cluster_num = 3;
% n*(n-1)/2
weights = ones(cluster_num*(cluster_num-1)/2,data_D);
%% training data weights
% * 随机梯度上升算法-在线学习
t = 1;
for index1 = 1:cluster_num-1
    for index2 = index1+1:cluster_num
        index_c = find((train_data(:,8)==index1)|(train_data(:,8)==index2));
        train_data_temp = train_data(index_c,:);
        train_data_temp(find((train_data_temp(:,8)==index1)),8) = 0;
        train_data_temp(find((train_data_temp(:,8)==index2)),8) = 1;
        %----------------------------
        for j = 1:100
            alpha = 0.1/j;
            for i = 1:length(train_data_temp)
                data = train_data_temp(i,1:end-1);
                h = 1.0/(1+exp(-(data*weights(t,:)‘)));
                error = train_data_temp(i,8) - h;
                weights(t,:) = weights(t,:) + (alpha * error * data);
            end
        end
        t = t + 1;
    end
end
%
%% test itself (the training data)
%
predict = zeros(length(train_data),cluster_num);
for i = 1:length(train_data)
    t = 1;
    data = train_data(i,1:end-1);
    for index1 = 1:cluster_num-1
        for index2 = index1+1:cluster_num
            h = 1.0/(1+exp(-(data*weights(t,:)‘)));
            if h < 0.5
                predict(i,index1) = predict(i,index1) + 1;
            else
                predict(i,index2) = predict(i,index2) + 1;
            end
            t = t + 1;
        end
    end
end 
[~,predict] = max((predict‘));
%% show the result
figure;
plot(train_data(:,8),‘+‘)
hold on
plot(predict,‘or‘);
hold on 
plot(abs(predict‘-train_data(:,8)));
axis([0,length(train_data),0,5])
accuracy = length(find(predict‘==train_data(:,8)))/length(train_data);
title([‘predict Training Data and the accuracy is :‘,num2str(accuracy)]);
%
%% predict the testing data
%
predict = zeros(length(test_data),cluster_num);
for i = 1:length(test_data)
    t = 1;
    data = test_data(i,1:end-1);
    for index1 = 1:cluster_num-1
        for index2 = index1+1:cluster_num
            h = 1.0/(1+exp(-(data*weights(t,:)‘)));
            if h < 0.5
                predict(i,index1) = predict(i,index1) + 1;
            else
                predict(i,index2) = predict(i,index2) + 1;
            end
            t = t + 1;
        end
    end
end 
[~,predict] = max((predict‘));
%% show the result
figure;
plot(test_data(:,8),‘+‘)
hold on
plot(predict,‘or‘);
hold on 
plot(abs(predict‘-test_data(:,8)));
axis([0,length(test_data),0,5])
accuracy = length(find(predict‘==test_data(:,8)))/length(test_data);
title([‘predict the testing data and the accuracy is :‘,num2str(accuracy)]);

训练样本本身结果:
技术分享
测试样本结果:
技术分享
程序中是一种投票表决的模式,采用多个二分类来进行的多分类。

版权声明:本文为博主原创文章,未经博主允许不得转载。

机器学习之logistic回归与分类

标签:机器学习   数据   logistic分类   

原文地址:http://blog.csdn.net/on2way/article/details/47359793

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!