2017-09-05 14:25:48 dangyalingengjia 阅读数 2036
  • Python机器学习经典案例实战

    Python在机器学习领域应用是非常广泛的,比如,我们可以使用机器学习进行验证码识别,使用机器学习实现计算机视觉项目,或者,我们也可以使用机器学习技术实现网页分类、文本挖掘、情感分析等等各种各样的事情。机器学习的重点在于算法,而算法的学习相对来说是比较枯燥的,所以,只有在学习的时候让算法跟实例结合,才能够让算法的学习变得不枯燥,并且也才能够更好的将理论运用与实践。

    3902 人正在学习 去看看 韦玮

学习了一点机器学习的内容:如何进行垃圾邮件分类。自己总结了一下。
试想一下我们人脑的思考方式,我们是如何判断一封邮件是垃圾邮件的:如果邮件中包含某些词,而且这些词出现的频率较高时(比如一封很短的邮件中只有几个Html标签,其中还包含“中奖”等词汇),我们把它归为“奇怪邮件”一类。当我们看了很多这样的“奇怪邮件”之后,我们判定这类邮件是我们所不需要的“垃圾邮件”,好在现在的邮箱都有垃圾箱可以帮我们分类。但是某一天我们收到腾讯客服的电话,我们真的中奖了,电话中说他们已经发了一封简短的邮件通知我,这是才焕然大悟,是不是那封邮件被当作垃圾邮件了,我们需要重新审视我们的分类标准。
那我们来试着模拟人脑的这个过程:
1,首先提取分类特征
首先需要获得一个垃圾邮件样本,然后统计样本中所有邮件中每一个单词出现的频率,并进行排序。从而得到分类特征词。
2,根据特征值计算新邮件是垃圾邮件的可能性。
新邮件中出现了某些“垃圾邮件特征词”,如何断定它是不是垃圾邮件呢。我们可以通过计算它是垃圾邮件的概率来判断。即计算出现特征词w1,…wn时,该邮件是垃圾邮件的条件概率。
介绍一下贝叶斯定理:
下面的图片截取自:http://www.chepoo.com/naive-bayesian-text-classification-algorithm-to-learn.html
贝叶斯定理
最终得出:
P(是垃圾邮件 | 含特征词w1,…wn) = P(含特征词w1 | 是垃圾邮件)*…P(wn | 是垃圾邮件) * P(是垃圾邮件) / (P(w1) * … P(wn))
如果此概率大于50%,我们认为是垃圾邮件。
注意:
这里如果某个P(含特征词w1 | 是垃圾邮件)为0的话,会使得最终结果为0,这被称为数据稀疏问题。为了解决这个问题,我们让每个特征词最少出现一次。
3,解决误杀和漏杀的问题。
如果确定有误杀及漏杀的情况,如何改进此模型呢?
这里猜测一下,是否可以通过调整P(w1 | 是垃圾邮件),来调整w1的判定权重呢?待以后学习后更新。

2017-04-27 10:43:27 quiet_girl 阅读数 1388
  • Python机器学习经典案例实战

    Python在机器学习领域应用是非常广泛的,比如,我们可以使用机器学习进行验证码识别,使用机器学习实现计算机视觉项目,或者,我们也可以使用机器学习技术实现网页分类、文本挖掘、情感分析等等各种各样的事情。机器学习的重点在于算法,而算法的学习相对来说是比较枯燥的,所以,只有在学习的时候让算法跟实例结合,才能够让算法的学习变得不枯燥,并且也才能够更好的将理论运用与实践。

    3902 人正在学习 去看看 韦玮

内容来自Andrew老师课程Machine Learning的第六章内容的Building a Spam Classifier部分。

一、Prioritizing What to Work on(优先考虑的工作)

在垃圾邮件分类的问题中,我们首先需要选出很多特征,根据这些特征使用训练集训练,然后使用验证集验证误差,最后使用这个模型预测结果。

在这个问题中,输入的x形式为:
也即:

Note:在邮件分类问题中,一般我们会选择10000-20000个在训练集中出现的比较频繁的单词。

怎样能够使垃圾分类器有更好的性能(最低的误分类率)?一般可以从以下几个方面入手:
(1)收集更多的数据,如“honeypot”project可以用来发送垃圾邮件,这些邮件可以当做训练集中的数据使用。
(2)找出基于路由信息的更复杂的特征(路由信息在邮件的header中)。
(3)寻找邮件主题内容的更复杂的特征,如:“discount”和“discounts”是否是同一个特征?“deal”和“Dealer”是否是同一个特征?以及标点符号特征。
(4)找出更复杂的算法来探测拼写错误,如m0rtgage,medlcine,w4tches等。
虽然我们知道有这些方法,但是具体哪些方法有效,这个很难说清楚,需要根据实际情况考虑。

二、Error Analysis(误差分析)

在学习的过程中,我们推荐的方法是(1)以一个简单的项目开始,在训练集上训练,在验证集上验证。(2)画出学习曲线帮助我们找出出现了什么问题,怎么解决,这部分内容参见Machine Learning第六讲[Advice for Applying Machine Learning] --(二)Diagnosing Bias vs. Variance内容。(3)误差分析:通过人工分析有多少数据被错误分类,并观察被错误分类的邮件主要是哪些内容或者哪些类别的内容。

举例:
验证集具有500个数据,发现有100个数据被错误分类,通过手动检测这100个错误分类的邮件,我们尝试去发现:
(1)这些邮件是什么类型的(type)?
(2)哪些特征可以帮助我们更好的分类这些邮件?

1、假设我们发现在这100个错误分类的邮件中,
Phrama:12
Replica/fake:4
Steal passwords:53
Other:31
我们发现Steal passwords(窃取密码)的这种邮件较多,那么我们需要把时间主要花费在这个上面来研究是否通过设计特征或者其他的方法来减小Steal passwords邮件的误分类率。

2、假如我们发现在这100个错误分类的邮件中,
Deliberate misspellings(m0rgage,medlcine,etc.):5
Unusual email routing:16
Unusual(Spamming) puctuation:32
我们发现拼写错误的比较少,因此我们没有必要把时间耗费在研究拼写错误上面。

我们知道了面对较高的误分类率我们应该怎么做,那么我们怎样衡量这么做是否有用呢?这就需要引入数值评估的内容了。
因为我们不能直接看出我们的方法对提高系统性能是否有帮助,唯一的办法就是利用量化的数值评估

比如,我们来衡量词干提取器有没有作用:
若在使用词干提取器之前误差率为5%,使用词干提取器之后误差率为3%,则说明提取器是有作用的(在后续学习中,这个评判数据还需要一些处理)。
2019-08-30 22:44:10 weixin_44720323 阅读数 19
  • Python机器学习经典案例实战

    Python在机器学习领域应用是非常广泛的,比如,我们可以使用机器学习进行验证码识别,使用机器学习实现计算机视觉项目,或者,我们也可以使用机器学习技术实现网页分类、文本挖掘、情感分析等等各种各样的事情。机器学习的重点在于算法,而算法的学习相对来说是比较枯燥的,所以,只有在学习的时候让算法跟实例结合,才能够让算法的学习变得不枯燥,并且也才能够更好的将理论运用与实践。

    3902 人正在学习 去看看 韦玮

机器学习实战 垃圾邮件文本分类正则匹配 re.split() ,分类错误问题解决

今天在看《机器学习实战》的时候,对文本的划分一直不理想,最后发现是书上正则化这一部分不是很正确。
书中的代码用了

def textParse(bigString): 
    import re
    listOfTokens = re.split(r'\\w*',bigString)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

但是划分不出数据,我从网上找了一下对代码改进了一下

def textParse(bigString): 
    import re
    listOfTokens = re.split(r'[!@#$%^&*()? \n~/]',bigString)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

这样划分之后结果就比较正常了。

在这里插入图片描述
参考文献:https://blog.csdn.net/CityzenOldwang/article/details/78398406

2014-12-04 21:30:26 hlx371240 阅读数 17334
  • Python机器学习经典案例实战

    Python在机器学习领域应用是非常广泛的,比如,我们可以使用机器学习进行验证码识别,使用机器学习实现计算机视觉项目,或者,我们也可以使用机器学习技术实现网页分类、文本挖掘、情感分析等等各种各样的事情。机器学习的重点在于算法,而算法的学习相对来说是比较枯燥的,所以,只有在学习的时候让算法跟实例结合,才能够让算法的学习变得不枯燥,并且也才能够更好的将理论运用与实践。

    3902 人正在学习 去看看 韦玮

本文讲介绍垃圾邮件分类,其中用到SVM算法、Logistic回归、SEA-Logistic深度网络分类。下面分别讲解这几个算法在垃圾邮件分类中的用法。

数据集为spamData.mat,训练集有3065个样本,测试集有1536个样本,每个样本的维度为57.

数据集下载地址:https://github.com/probml/pmtkdata/tree/master/spamData

一、SVM分类

二、Logistic分类

三、SEA-Logistic分类


、SVM分类

    原理我就不讲了,前面博文有,而且网上有太多了资料,还有我没有别人讲的好,不能献丑了,我现在只讲如何利用Libsvm、MATLAB自带的svm工具箱分类垃圾邮件。

1.libsvm垃圾邮件分类

libsvm库下载:http://www.csie.ntu.edu.tw/~cjlin/libsvm/

详解:http://www.matlabsky.com/thread-11925-1-1.html

下载好的libsvm,然后添加到主路径下File->set path ->add with subfolders->加入libsvm-3.11文件夹的路径。

1.首先在MATLAB命令窗【Commond Window】中输入:mex -setup

2.出现 Would you like mex to locate installed compilers [y]/n?  选择y

3.Select a compiler: 
[1] Microsoft Visual C++ 2010 in E:\VS2010 
[0] None                                                                         
选择:1

4.Are these correct [y]/n? 选择y

好了现在就可以用了

load('spamData.mat');
model = svmtrain(ytrain,Xtrain,'-t 0');
[predict_label,accuracy] = svmpredict(ytest,Xtest,model);
上面加红色标注的-t x  x可以取0,1,2,3,4。系统默认为2,如果不加-t x

0)线性核函数 
1)多项式核函数 
2)RBF核函数 
3)sigmoid核函数 
4)自定义核函数


从上表可以看出,线性核函数效果最好,能够达到91.1458%。

数据要这样处理下:

ytrain(ytrain==0) = -1;
ytest(ytest==0) = -1;


2.MATLAB自带的svm工具箱分类垃圾邮件

    Matlab自带了svm工具箱,现在我就介绍如何利用这个工具箱来做垃圾邮件分类。下面我先给出程序,再来解释。

load spamData
svmStruct = svmtrain(Xtrain,ytrain,'showplot',true);
classes=svmclassify(svmStruct,Xtest,'showplot',true);
nCorrect=sum(classes==ytest);
accuracy = nCorrect/length(classes);
accuracy = 100*accuracy;
accuracy = double(accuracy);
fprintf('accuracy=%s%%\n',accuracy);

运行会出现这个结果就忽略它,对结果没有什么影响。

在程序中点击右键打开svmtrain.m这个文件。在文件的dflts ={'linear',.......},我得是287行。可以改变核函数,可以选择okfuns = {'linear','quadratic', 'radial','rbf','polynomial','mlp'}; 上面dflts ={'linear',.......}可以改变。

linear是线性核

quadratic是二次核函数。

radial是什么核?

rbf 是径向基核,通常叫做高斯核,但是Ng说跟高斯没有什么关系。

polynomial是多项式核。

mlp多层感知器核函数。


下面来看使用各个核在垃圾邮件分类中的识别率


可以看到二次核函数效果最好,能达到85.55%。


整理的数据集见资源,三种不同的预处理方式

给出Excise8.1的作业结果

logistic回归


SVM


二、Logistic分类

     可以参考这篇文献:http://www.docin.com/p-160363677.html

前面的博文讲过softmax分类,可以改为Logistic回归。http://blog.csdn.net/hlx371240/article/details/40015395

这篇博文是在《最优化计算方法》这门课写的,当时用LBFGS和SD法优化参数,现在我用工具箱直接进行分类。

%% STEP 0: Initialise constants and parameters
inputSize = 57; % Size of input vector 
numClasses = 2;     % Number of classes 
lambda = 1e-4; % Weight decay parameter
%%=====================================================================
%% STEP 1: Load data
load('D:\机器学习课程\作业三\spamData.mat');
Xtrain=Xtrain';
ytrain(ytrain==0) = 2; % Remap 0 to 10
inputData = Xtrain;
DEBUG = false;
if DEBUG
    inputSize = 8;
    inputData = randn(8, 100);
    labels = randi(10, 100, 1);
end
% Randomly initialise theta
theta = 0.005 * randn(numClasses * inputSize, 1);%输入的是一个列向量
%%======================================================================
%% STEP 2: Implement softmaxCost
[cost, grad] = softmaxCost(theta, numClasses, inputSize, lambda, inputData, ytrain);                                   
%%======================================================================
%% STEP 3: Learning parameters
options.maxIter = 100;
softmaxModel = softmaxTrain(inputSize, numClasses, lambda, ...
                            inputData, ytrain, options);
%%======================================================================
%% STEP 4: Testing
Xtest=Xtest';
ytest(ytest==0) = 2; % Remap 0 to 10
size(softmaxModel.optTheta)
size(inputData)
[pred] = softmaxPredict(softmaxModel, Xtest);
acc = mean(ytest(:) == pred(:));
fprintf('Accuracy: %0.3f%%\n', acc * 100);
softmaxTrain.m

<span style="font-family:Times New Roman;">function [softmaxModel] = softmaxTrain(inputSize, numClasses, lambda, inputData, labels, options)
if ~exist('options', 'var')
    options = struct;
end
if ~isfield(options, 'maxIter')
    options.maxIter = 400;
end
% initialize parameters
theta = 0.005 * randn(numClasses * inputSize, 1);
% Use minFunc to minimize the function
addpath minFunc/
options.Method = 'lbfgs'; % Here, we use L-BFGS to optimize our cost
                          % function. Generally, for minFunc to work, you
                          % need a function pointer with two outputs: the
                          % function value and the gradient. In our problem,
                          % softmaxCost.m satisfies this.
minFuncOptions.display = 'on';
[softmaxOptTheta, cost] = minFunc( @(p) softmaxCost(p, ...
                                   numClasses, inputSize, lambda, ...
                                   inputData, labels), ...                                   
                              theta, options);
% Fold softmaxOptTheta into a nicer format
softmaxModel.optTheta = reshape(softmaxOptTheta, numClasses, inputSize);
softmaxModel.inputSize = inputSize;
softmaxModel.numClasses = numClasses;                       
end                   

softmaxCost.m

<span style="font-size:14px;">function [cost, grad] = softmaxCost(theta, numClasses, inputSize, lambda, data, labels)

% numClasses - the number of classes 
% inputSize - the size N of the input vector
% lambda - weight decay parameter
% data - the N x M input matrix, where each column data(:, i) corresponds to
%        a single test set
% labels - an M x 1 matrix containing the labels corresponding for the input data
%

% Unroll the parameters from theta
theta = reshape(theta, numClasses, inputSize);%将输入的参数列向量变成一个矩阵

numCases = size(data, 2);%输入样本的个数
groundTruth = full(sparse(labels, 1:numCases, 1));%这里sparse是生成一个稀疏矩阵,该矩阵中的值都是第三个值1
                                                    %稀疏矩阵的小标由labels和1:numCases对应值构成
cost = 0;
thetagrad = zeros(numClasses, inputSize);
M = bsxfun(@minus,theta*data,max(theta*data, [], 1));
M = exp(M);
p = bsxfun(@rdivide, M, sum(M));
cost = -1/numCases * groundTruth(:)' * log(p(:)) + lambda/2 * sum(theta(:) .^ 2);
thetagrad = -1/numCases * (groundTruth - p) * data' + lambda * theta;

grad = [thetagrad(:)];
end</span>


softmaxPredict.m

function [pred] = softmaxPredict(softmaxModel, data)
% Unroll the parameters from theta
theta = softmaxModel.optTheta;  % this provides a numClasses x inputSize matrix
pred = zeros(1, size(data, 2));
[nop, pred] = max(theta * data);
end

initializeParameters.m

<span style="font-family:Times New Roman;">function theta = initializeParameters(hiddenSize, visibleSize)
%% Initialize parameters randomly based on layer sizes.
r  = sqrt(6) / sqrt(hiddenSize+visibleSize+1);   % we'll choose weights uniformly from the interval [-r, r]
W1 = rand(hiddenSize, visibleSize) * 2 * r - r;
W2 = rand(visibleSize, hiddenSize) * 2 * r - r;
b1 = zeros(hiddenSize, 1);
b2 = zeros(visibleSize, 1);
% Convert weights and bias gradients to the vector form.
% This step will "unroll" (flatten and concatenate together) all 
% your parameters into a vector, which can then be used with minFunc. 
theta = [W1(:) ; W2(:) ; b1(:) ; b2(:)];
end
sigmoidInv.m

function sigmInv = sigmoidInv(x)
    sigmInv = sigmoid(x).*(1-sigmoid(x));
end

这个算法利用的LBFGS,拟牛顿法,可以节约内存,用近似的Hessian矩阵代替精确的Hessian矩阵,这个是我的美女老师讲的,建议同学们选下学期美女老师的《数值优化》的课程,我觉得她讲得很好,听课绝对认真。

还有一个工具箱(minfunc)到资源下载。

最后得到的识别率为:92.057%。但是不是每次跑出来的程序都是这个识别率,因为参数是随机产生的。


三、SAE-Logistic分类
       SAE全称为Sparse Auto Encoder,是加了一层自学习层进一步提取特征,因为邮件中每个词的出现可能存在某种关联,然后再分类,这也是神经网络提取特征。 

    可以参考这篇文献:http://nlp.stanford.edu/~socherr/sparseAutoencoder_2011new.pdf

       博文:http://blog.csdn.net/hlx371240/article/details/40201499

网络结果如下图所示:

main.m
<span style="color:#3333ff;font-size:18px; font-weight: bold; font-family: 'Times New Roman';">%STEP 2: 初始化参数和load数据
</span><span style="font-family:Times New Roman;font-size:14px;">clear all;
clc;
load('D:\机器学习课程\作业三\spamData.mat');
Xtrain=Xtrain';
ytrain(ytrain==0) = 2;
Xtest=Xtest';
ytest(ytest == 0) = 2; % Remap 0 to 10
inputSize  = 57;
numLabels  = 2;
a=[57 50 45 40 35 30 25 20 15 10 5];
sparsityParam = 0.1;
lambda = 3e-3;       % weight decay parameter
beta = 3;            % weight of sparsity penalty term
numClasses = 2;     % Number of classes (MNIST images fall into 10 classes)
lambda = 1e-4; % Weight decay parameter
%% ======================================================================
%STEP 2: 训练自学习层SAE
for i=1:11
    hiddenSize = a(i);
    theta = initializeParameters(hiddenSize, inputSize);
    %-------------------------------------------------------------------
    opttheta = theta;
    addpath minFunc/
    options.Method = 'lbfgs';
    options.maxIter = 400;
    options.display = 'on';
    [opttheta, loss] = minFunc( @(p) sparseAutoencoderCost(p, ...
        inputSize, hiddenSize, ...
        lambda, sparsityParam, ...
        beta, Xtrain), ...
        theta, options);
    trainFeatures = feedForwardAutoencoder(opttheta, hiddenSize, inputSize, ...
        Xtrain);
    %% ================================================
    %STEP 3: 训练Softmax分类器
    saeSoftmaxTheta = 0.005 * randn(hiddenSize * numClasses, 1);
    softmaxLambda = 1e-4;
    numClasses = 2;
    softoptions = struct;
    softoptions.maxIter = 500;
    softmaxModel = softmaxTrain(hiddenSize,numClasses,softmaxLambda,...
        trainFeatures,ytrain,softoptions);
    theta_new = softmaxModel.optTheta(:);
    %% ============================================================
    stack = cell(1,1);
    stack{1}.w = reshape(opttheta(1:hiddenSize * inputSize), hiddenSize, inputSize);
    stack{1}.b =opttheta(2*hiddenSize*inputSize+1:2*hiddenSize*inputSize+hiddenSize);
    [stackparams, netconfig] = stack2params(stack);
    stackedAETheta = [theta_new;stackparams];
    addpath minFunc/;
    options = struct;
    options.Method = 'lbfgs';
    options.maxIter = 400;
    options.display = 'on';
    [stackedAEOptTheta,cost] =  minFunc(@(p)stackedAECost(p,inputSize,hiddenSize,numClasses, netconfig,lambda, Xtrain, ytrain),stackedAETheta,options);
    %% =================================================================
    %STEP 4: 测试
    [pred] = stackedAEPredict(stackedAEOptTheta, inputSize, hiddenSize, ...
        numClasses, netconfig, Xtest);
    acc = mean(ytest(:) == pred(:));
    fprintf('Accuracy = %0.3f%%\n', acc * 100);
    result(i)=acc * 100;
end</span><span style="color:#3333ff;font-size:18px; font-weight: bold; font-family: 'Times New Roman';">
</span>
stackedAEPredict.m
<span style="font-family:Times New Roman;font-size:14px;">function [pred] = stackedAEPredict(theta, inputSize, hiddenSize, numClasses, netconfig, data)                     
softmaxTheta = reshape(theta(1:hiddenSize*numClasses), numClasses, hiddenSize);
stack = params2stack(theta(hiddenSize*numClasses+1:end), netconfig);
depth = numel(stack);
z = cell(depth+1,1);
a = cell(depth+1, 1);
a{1} = data;
for layer = (1:depth)
  z{layer+1} = stack{layer}.w * a{layer} + repmat(stack{layer}.b, [1, size(a{layer},2)]);
  a{layer+1} = sigmoid(z{layer+1});
end
[~, pred] = max(softmaxTheta * a{depth+1});
end
% You might find this useful
function sigm = sigmoid(x)
    sigm = 1 ./ (1 + exp(-x));
end</span>
stackedAECost.m
<span style="font-family:Times New Roman;font-size:14px;">function [ cost, grad ] = stackedAECost(theta, inputSize, hiddenSize, ...
                                              numClasses, netconfig, ...
                                              lambda, data, labels)                                       
% stackedAECost: Takes a trained softmaxTheta and a training data set with labels,
% and returns cost and gradient using a stacked autoencoder model. Used for
% finetuning.                                         
% theta: trained weights from the autoencoder
% visibleSize: the number of input units
% hiddenSize:  the number of hidden units *at the 2nd layer*
% numClasses:  the number of categories
% netconfig:   the network configuration of the stack
% lambda:      the weight regularization penalty
% data: Our matrix containing the training data as columns.  So, data(:,i) is the i-th training example. 
% labels: A vector containing labels, where labels(i) is the label for the
softmaxTheta = reshape(theta(1:hiddenSize*numClasses), numClasses, hiddenSize);
stack = params2stack(theta(hiddenSize*numClasses+1:end), netconfig);
% You will need to compute the following gradients
softmaxThetaGrad = zeros(size(softmaxTheta));
stackgrad = cell(size(stack));
for d = 1:numel(stack)
    stackgrad{d}.w = zeros(size(stack{d}.w));
    stackgrad{d}.b = zeros(size(stack{d}.b));
end
cost = 0; % You need to compute this
numCases = size(data, 2);%输入样本的个数
groundTruth = full(sparse(labels, 1:numCases, 1));
depth = numel(stack);
z = cell(depth+1,1);
a = cell(depth+1, 1);
a{1} = data;
for layer = (1:depth)
  z{layer+1} = stack{layer}.w * a{layer} + repmat(stack{layer}.b, [1, size(a{layer},2)]);
  a{layer+1} = sigmoid(z{layer+1});
end
M = softmaxTheta * a{depth+1};
M = bsxfun(@minus, M, max(M));
p = bsxfun(@rdivide, exp(M), sum(exp(M)));
cost = -1/numClasses * groundTruth(:)' * log(p(:)) + lambda/2 * sum(softmaxTheta(:) .^ 2);
softmaxThetaGrad = -1/numClasses * (groundTruth - p) * a{depth+1}' + lambda * softmaxTheta;
d = cell(depth+1);
d{depth+1} = -(softmaxTheta' * (groundTruth - p)) .* a{depth+1} .* (1-a{depth+1});
for layer = (depth:-1:2)
  d{layer} = (stack{layer}.w' * d{layer+1}) .* a{layer} .* (1-a{layer});
end
for layer = (depth:-1:1)
  stackgrad{layer}.w = (1/numClasses) * d{layer+1} * a{layer}';
  stackgrad{layer}.b = (1/numClasses) * sum(d{layer+1}, 2);
end
% -------------------------------------------------------------------------
%% Roll gradient vector
grad = [softmaxThetaGrad(:) ; stack2params(stackgrad)];
end
% You might find this useful
function sigm = sigmoid(x)
    sigm = 1 ./ (1 + exp(-x));
end</span>
feedForwardAutoencoder.m
<span style="font-family:Times New Roman;font-size:14px;">function [activation] = feedForwardAutoencoder(theta, hiddenSize, visibleSize, data)
% theta: trained weights from the autoencoder
% visibleSize: the number of input units (probably 64) 
% hiddenSize: the number of hidden units (probably 25) 
% data: Our matrix containing the training data as columns.  So, data(:,i) is the i-th training example. 
% We first convert theta to the (W1, W2, b1, b2) matrix/vector format, so that this 
% follows the notation convention of the lecture notes. 
W1 = reshape(theta(1:hiddenSize*visibleSize), hiddenSize, visibleSize);
b1 = theta(2*hiddenSize*visibleSize+1:2*hiddenSize*visibleSize+hiddenSize);
%  Instructions: Compute the activation of the hidden layer for the Sparse Autoencoder.
activation  = sigmoid(W1*data+repmat(b1,[1,size(data,2)]));
end
function sigm = sigmoid(x)
    sigm = 1 ./ (1 + exp(-x));
end</span>
sparseAutoencoderCost.m
<span style="font-family:Times New Roman;font-size:14px;">function [cost,grad] = sparseAutoencoderCost(theta, visibleSize, hiddenSize, ...
                                             lambda, sparsityParam, beta, data)
% visibleSize: the number of input units (probably 64) 
% hiddenSize: the number of hidden units (probably 25) 
% lambda: weight decay parameter
% sparsityParam: The desired average activation for the hidden units (denoted in the lecture
%                           notes by the greek alphabet rho, which looks like a lower-case "p").
% beta: weight of sparsity penalty term
% data: Our 64x10000 matrix containing the training data.  So, data(:,i) is the i-th training example. 
% The input theta is a vector (because minFunc expects the parameters to be a vector). 
% We first convert theta to the (W1, W2, b1, b2) matrix/vector format, so that this 
% follows the notation convention of the lecture notes. 
W1 = reshape(theta(1:hiddenSize*visibleSize), hiddenSize, visibleSize);
W2 = reshape(theta(hiddenSize*visibleSize+1:2*hiddenSize*visibleSize), visibleSize, hiddenSize);
b1 = theta(2*hiddenSize*visibleSize+1:2*hiddenSize*visibleSize+hiddenSize);
b2 = theta(2*hiddenSize*visibleSize+hiddenSize+1:end);
% Cost and gradient variables (your code needs to compute these values). 
% Here, we initialize them to zeros. 
cost = 0;
W1grad = zeros(size(W1)); 
W2grad = zeros(size(W2));
b1grad = zeros(size(b1)); 
b2grad = zeros(size(b2));

Jcost = 0;%直接误差
Jweight = 0;%权值惩罚
Jsparse = 0;%稀疏性惩罚
[n m] = size(data);%m为样本的个数,n为样本的特征数
%前向算法计算各神经网络节点的线性组合值和active值
z2 = W1*data+repmat(b1,1,m);%注意这里一定要将b1向量复制扩展成m列的矩阵
a2 = sigmoid(z2);
z3 = W2*a2+repmat(b2,1,m);
a3 = sigmoid(z3);
% 计算预测产生的误差
Jcost = (0.5/m)*sum(sum((a3-data).^2));
%计算权值惩罚项
Jweight = (1/2)*(sum(sum(W1.^2))+sum(sum(W2.^2)));
%计算稀释性规则项
rho = (1/m).*sum(a2,2);%求出第一个隐含层的平均值向量
Jsparse = sum(sparsityParam.*log(sparsityParam./rho)+ ...
        (1-sparsityParam).*log((1-sparsityParam)./(1-rho)));
%损失函数的总表达式
cost = Jcost+lambda*Jweight+beta*Jsparse;
%反向算法求出每个节点的误差值
d3 = -(data-a3).*sigmoidInv(z3);
sterm = beta*(-sparsityParam./rho+(1-sparsityParam)./(1-rho));%因为加入了稀疏规则项,所以
                                                            %计算偏导时需要引入该项
d2 = (W2'*d3+repmat(sterm,1,m)).*sigmoidInv(z2); 
%计算W1grad 
W1grad = W1grad+d2*data';
W1grad = (1/m)*W1grad+lambda*W1;
%计算W2grad  
W2grad = W2grad+d3*a2';
W2grad = (1/m).*W2grad+lambda*W2;
%计算b1grad 
b1grad = b1grad+sum(d2,2);
b1grad = (1/m)*b1grad;%注意b的偏导是一个向量,所以这里应该把每一行的值累加起来
%计算b2grad 
b2grad = b2grad+sum(d3,2);
b2grad = (1/m)*b2grad;
grad = [W1grad(:) ; W2grad(:) ; b1grad(:) ; b2grad(:)];
end

function sigm = sigmoid(x)
    sigm = 1 ./ (1 + exp(-x));
end
function sigmInv = sigmoidInv(x)
    sigmInv = sigmoid(x).*(1-sigmoid(x));
end</span>
stack2params.m
<span style="font-family:Times New Roman;font-size:14px;">function [params, netconfig] = stack2params(stack)

params = [];
for d = 1:numel(stack)
    params = [params ; stack{d}.w(:) ; stack{d}.b(:) ];
    assert(size(stack{d}.w, 1) == size(stack{d}.b, 1), ...
        ['The bias should be a *column* vector of ' ...
         int2str(size(stack{d}.w, 1)) 'x1']);
    if d < numel(stack)
        assert(size(stack{d}.w, 1) == size(stack{d+1}.w, 2), ...
            ['The adjacent layers L' int2str(d) ' and L' int2str(d+1) ...
             ' should have matching sizes.']);
    end
end
if nargout > 1
    % Setup netconfig
    if numel(stack) == 0
        netconfig.inputsize = 0;
        netconfig.layersizes = {};
    else
        netconfig.inputsize = size(stack{1}.w, 2);
        netconfig.layersizes = {};
        for d = 1:numel(stack)
            netconfig.layersizes = [netconfig.layersizes ; size(stack{d}.w,1)];
        end
    end
end
end</span>

实验结果:


从图中可以看出识别率基本都在90%以上,当隐含层的神经元为25个时候,识别率达到93.36%

综上几种方法识别率

可以看出,SAE-Logistic>Logistic>Libsvm>SVM-MATLAB.可以看出SAE-Logistic的识别率最高,所以这就是deep learning深度网络的魅力所在。



怀柔风光



2019-04-05 18:26:49 weixin_44750583 阅读数 408
  • Python机器学习经典案例实战

    Python在机器学习领域应用是非常广泛的,比如,我们可以使用机器学习进行验证码识别,使用机器学习实现计算机视觉项目,或者,我们也可以使用机器学习技术实现网页分类、文本挖掘、情感分析等等各种各样的事情。机器学习的重点在于算法,而算法的学习相对来说是比较枯燥的,所以,只有在学习的时候让算法跟实例结合,才能够让算法的学习变得不枯燥,并且也才能够更好的将理论运用与实践。

    3902 人正在学习 去看看 韦玮

6.1.SVM建立垃圾邮件分类器

1)题目:

如今,许多电子邮件服务提供垃圾邮件过滤器,能够将电子邮件精确地分类为垃圾邮件和非垃圾邮件。在本部分练习中,您将使用SVM构建自己的垃圾邮件过滤器。
您将训练一个分类器来分类给定的电子邮件x是垃圾邮件(y = 1)还是非垃圾邮件(y = 0)。特别地,你需要将每封电子邮件转换成一个特征向量xRnx\in R^n
本练习中包含的数据集是基于SpamAssassin Public Corpus(http://spamassassin.apache.org/old/publiccorpus/ )的一个子集,对于本练习,您将只使用电子邮件正文(不包括邮件抬头)。
数据集链接: https://pan.baidu.com/s/1cEgQIvehUcLxZ0WVhxcPuQ 提取码: xejn

2)大致步骤:

  • 邮件预处理。首先读取样例邮件查看下。然后进行预处理:
    1.把整封邮件转化为小写
    2.移除所有HTML标签(超文本标记语言)
    3.将所有的URL替换为’httpaddr’
    4.将所有的地址替换为’emailaddr’
    5.将所有数字替换为’number’
    6.将所有美元符号($)替换为’dollar’
    7.将所有单词还原为词根。例如,“discount”, “discounts”, “discounted” and “discounting”都替换为“discount”
    8.移除所有非文字类型,所有的空格(tabs, newlines, spaces)调整为一个空格
    然后再对照单词表得到样例对应的序号列。
  • 提取特征。利用序号列得到邮件的一个特征向量,xRnx\in R^n,这里是一个1899维的特征向量。
  • 训练SVM。取C=0.1,核函数为线性核,用训练集训练出模型,训练精度为99.8%,再在测试集上测试,精度为98.9%。
  • 打印权重最高的前15个词,邮件中出现这些词更容易是垃圾邮件
  • 用训练好的模型预测已给的四封邮件

3)关于Python:

  • .lower( )可以转化为小写。

  • 邮件预处理时需要用到re模块,正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为”元字符”)组成的文字模式。re模块中的函数让你检查一个特定的字符串是否匹配给定的正则表达式(或给定的正则表达式是否匹配特定的字符串,这可归结为同一件事)。
    使用re.sub(pattern, repl, string, count=0, flags=0)
    pattern是需要被替换的部分,repl为替换之后的内容,string为查找的范围,count表示模式匹配后替换的最大次数,默认0表示替换所有的匹配。

  • re.split( ) 用来分割字符串。注意在分割时候不能直接用吴恩达给出的MATLAB的代码,因为有一些需要转义。

  • nltk的全称是natural languagetoolkit,是一套基于python的自然语言处理工具集。这里主要使用了词干提取的Porter提取算法。nltk.stem.PorterStemmer( )

  • try和except语句块可以用来运行可能会有问题的代码。

  • 在循环中不想要某些条件执行后面的代码可以用continue跳过本次循环直接进行下一次循环。

  • sorted函数直接对数组进行排序,np.argsort是返回排序后的坐标。

  • 关于正则表达式:
    字符”r“的意思是表示忽略后面的转义字符,这样简化了后面正则表达式里每遇到一个转义字符还得挨个转义的麻烦;[ ]里面可以用来填要匹配的字符集;\是转义字符,让它后面的字符还原它原有的含义;*匹配前面的子表达式零次或多次;+匹配前面的子表达式一次或多次;$表示只在字符末尾进行匹配。。。这里引用第一个链接里的一些表格以备后用~
    更多可参考 http://www.runoob.com/regexp/regexp-syntax.htmlhttps://blog.csdn.net/u010254900/article/details/22038741

字符 描述
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用\( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用\ +。
. 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用\ ?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。

4) 代码与结果:


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.io as scio
from sklearn import svm 
import re #处理正则表达式的模块
import nltk #自然语言处理工具包

'''============================part1 邮件预处理========================='''
#查看样例邮件
f = open('emailSample1.txt', 'r').read()
print(f)

def processEmail(email):
    email = email.lower() #转化为小写
    email = re.sub('<[^<>]+>', ' ', email) #移除所有HTML标签
    email = re.sub('(http|https)://[^\s]*', 'httpaddr', email) #将所有的URL替换为'httpaddr'
    email = re.sub('[^\s]+@[^\s]+', 'emailaddr', email) #将所有的地址替换为'emailaddr'
    email = re.sub('\d+', 'number', email) #将所有数字替换为'number'
    email = re.sub('[$]+', 'dollar', email) #将所有美元符号($)替换为'dollar'
    
    #将所有单词还原为词根//移除所有非文字类型,空格调整
    stemmer = nltk.stem.PorterStemmer() #使用Porter算法
    tokens = re.split('[ @$/#.-:&*+=\[\]?!()\{\},\'\">_<;%]', email) #把邮件分割成单个的字符串,[]里面为各种分隔符
    tokenlist = []
    for token in tokens:
        token = re.sub('[^a-zA-Z0-9]', '', token) #去掉任何非字母数字字符
        try: #porterStemmer有时会出现问题,因此用try
            token = stemmer.stem(token) #词根
        except:
            token = ''
        if len(token) < 1: 
            continue #字符串长度小于1的不添加到tokenlist里
        tokenlist.append(token)
    
    return tokenlist

#查看处理后的样例
processed_f = processEmail(f)
for i in processed_f:
    print(i, end=' ')

#得到单词表,序号为索引号+1
vocab_list = np.loadtxt('vocab.txt', dtype='str', usecols=1)
#得到词汇表中的序号
def word_indices(processed_f, vocab_list):
    indices = []
    for i in range(len(processed_f)):
        for j in range(len(vocab_list)):
            if processed_f[i]!=vocab_list[j]:
                continue
            indices.append(j+1)
    return indices

#查看样例序号
f_indices = word_indices(processed_f, vocab_list)
for i in f_indices:
    print(i, end=' ')


'''============================part2 提取特征========================='''
def emailFeatures(indices):
    features = np.zeros((1899))
    for each in indices:
        features[each-1] = 1 #若indices在对应单词表的位置上词语存在则记为1
    return features
        
sum(emailFeatures(f_indices)) #45


'''============================part3 训练SVM========================='''
#训练模型
train = scio.loadmat('spamTrain.mat')
train_x = train['X']
train_y = train['y']

clf = svm.SVC(C=0.1, kernel='linear')
clf.fit(train_x, train_y)

#精度
def accuracy(clf, x, y):
    predict_y = clf.predict(x)
    m = y.size
    count = 0
    for i in range(m):
        count = count + np.abs(int(predict_y[i])-int(y[i])) #避免溢出错误得到225
    return 1-float(count/m) 

accuracy(clf, train_x, train_y) #0.99825

#测试模型
test = scio.loadmat('spamTest.mat')
accuracy(clf, test['Xtest'], test['ytest']) #0.989


'''============================part4 高权重词========================='''
#打印权重最高的前15个词,邮件中出现这些词更容易是垃圾邮件
i = (clf.coef_).size-1
while i >1883:
    #返回从小到大排序的索引,然后再打印
    print(vocab_list[np.argsort(clf.coef_).flatten()[i]], end=' ')
    i = i-1

'''============================part5 预测邮件========================='''

t = open('spamSample2.txt', 'r').read()
#预处理
processed_f = processEmail(t) 
f_indices = word_indices(processed_f, vocab_list)
#特征提取
x = np.reshape(emailFeatures(f_indices), (1,1899))
#预测
clf.predict(x)

查看样例邮件
在这里插入图片描述

预处理后的样例(吴恩达给出的作业中的样例不对,visitor you re 他给分为visitor your了,这是由于在分割的时候是否把’ 作为分割,这样会导致后面特征提取后少一个非零项,即只有44项)
在这里插入图片描述

样例对应的词汇序号
在这里插入图片描述

训练精度和测试精度
在这里插入图片描述

15个权重最高的词,和作业中有些微差别
在这里插入图片描述

测试了给出的四封邮件,都正确分类,下面是spamSample2的结果,分类器把它分为垃圾邮件
在这里插入图片描述

本次作业没有给出知识点概括,因为上次作业6.0已经大概描述清楚了SVM的原理和模型选择的一些内容,这次作业其实主要是对练习怎么从文本中提取特征得到一个n维的特征向量,再进行模型训练。
文本提取和处理也是很难啊~ 继续学吧!

没有更多推荐了,返回首页