sourcecode is half done

This commit is contained in:
StarLee 2016-06-21 11:04:00 +08:00
parent 73970eca34
commit e374520544
13 changed files with 302 additions and 150 deletions

BIN
LG_arch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -1,149 +0,0 @@
\documentclass[a4paper,12pt,UTF8,titlepage]{ctexart}
%页边距
\usepackage{geometry}
\geometry{left=2.0cm,right=2.0cm,top=2.5cm,bottom=2.5cm}
%页眉
\usepackage{fancyhdr}
\pagestyle{fancy}
\lhead{李志星 15060025 }
\chead{Spark MLlib应用报告}
\rhead{\leftmark}
%文档信息/同时也用于生成报告封面
\author{李志星\\ 15060025}
\title{\Huge MLlib中Logistic Regression的应用}
\usepackage{graphicx}
\usepackage{subfigure}
\DeclareGraphicsExtensions{.eps,.ps,.jpg,.bmp,.gif,.png}
\usepackage{pythonhighlight}
\begin{document}
\maketitle
\section{前言}
\subsection{手写识别}
手写识别Handwriting recognition是计算机在纸、照片、触摸屏或其他设备中接收并识别人手写的文字等信息的技术主要应用于光学字符识别OCR。手写识别系统能够用来识别汉字、英语、数字等字符。不过本报告的重点不在手写识别而在于理解MLlib中的logistic回归因此以识别数字为例。识别数字09是个十类别问题logistic回归最常用的场景是二分类如果要用logistic回归解决这个问题要采用one-against-one和one-against-all等做法进行处理虽然复杂些但是基本原理是一样的。因此本报告把主要关注点放在对MLlib算法的研究只利用0和1的样本从而解决二分类问题。
\subsection{Logistic Regression}
\subsection{MLlib算法主要机制}
在MLlib中有许多的概念其中对理解其算法比较重要的有\emph{DataFrame}\emph{Pipeline}\emph{Transfromer}\emph{Estimator}
\begin{itemize}
\item DataFrameMLlib使用SaprkSQL中DataFrame来操作数据集是最近才添加的API。在MLLib模块中有两个包都可以用来调用机器学习算法mllib和ml。mllibRDD操作而ml基于DataFrameml是官方推荐使用的。通过\emph{DataFrame}可以操作各种各样的数据:文本、图像和结构化数据等。\emph{DataFrame}以命名列的方式组织的分布式数据集 等同于关系型数据库中的一个表和R/Python中的\emph{DataFrame}类似,不过进行了很多的优化。
\item Pipeline在MLlib中有一个很关键的概念\emph{Pipeline}。在利用解决机器学习问题时经常要用对数据进行一系列的处理MLlib用\emph{Pipeline}来表示这样的工作流,在\emph{Pipeline}中,包含一组以一定顺序执行的\emph{ PipelineStage}( \emph{Transformer}\emph{Estimator})。
\item TransformerTransformer是对特征转换和学习得到的模型的抽象每一个\emph{Transfromer}都要实现transform()方法,它把一个\emph{DataFrame}处理后得到另一个\emph{DataFrame},一般来说新的DataFrame比原来的DataFrame要多一些列。
\item EstimatorEstimator是对一些机器学习算法或者其他的数据处理算法的抽象每一个\emph{Estimator}都有一个方法fit(),它以\emph{DataFrame}为参数,返回一个模型,也就是\emph{Transformer}比如在MLlib中 LogisticRegression 就是一个\emph{Estimator}而LogisticRegressionModel就是一个\emph{Transformer}
\end{itemize}
一个比较简单形象的例子就是文本文档的处理,如下图*所示,上面一行表示了一个包含3个stage的Pipeline前两个Tokenizer和HashingTF是Transformer,第三个LogisticRegression是一个Estimer。下面一行是一个流经pipeline的数据流,圆柱体代表了DataFrame.当调用pipeline的fit方法时 Tokenizer.transform() 把原始的Raw text切分成单词然后把这些单词添加到原DataFrame中形成新的DataFrame从而让HashingTF.transfore()进行处理他把单词列转化成特征矩阵又添加到新的DataFrame中最后通过 LogisticRegression.fit()方法产生LogisticRegressionModel。生成的模型可以用于后续的测试等。
\begin{figure}[h!]
\centering
\includegraphics[width=16cm]{pipeline.jpg}
\caption{MLlib pipeline}
\label{pipeline}
\end{figure}
\section{解决方案}
\subsection{数据集}
本报告用到的数据集是我从网上搜集到的一个文本文件对应一个样本里面包含一个32*32的0/1矩阵矩阵中每一个点相当于手写图像处理后一个像素点的值如下图*。训练数据和测试数据中分别有300和76个样本。
\begin{figure}[h!]
\centering
\subfigure[数字0对应的一个样本]{
\label{0} %% label for first subfigure
\includegraphics[width=1.0in]{data_0.jpg}}
\hspace{0.2in}
\subfigure[数字1对应的一个样本]{
\label{1} %% label for second subfigure
\includegraphics[width=1.0in]{data_1.jpg}}
\caption{样本示例}
\label{0_1} %% label for entire figure
\end{figure}
\subsection{代码}
如前言中所述MLlib中有两个用于机器学习的包mllib和ml根据应用趋势和其官方网站的建议我采用了ml。详细代码见文件***.py。代码解释如下
\subsubsection{导入依赖}
此段代码导入需要用到的包包括数据处理的Vectors、算法训练的 LogisticRegression、算法评估BinaryClassificationEvaluator以及其他的一些用于和Spark操作的包。
\begin{python}
from pyspark import SparkContext
from pyspark.sql import SQLContext
from pyspark.ml.classification import LogisticRegression
from pyspark.mllib.linalg import Vectors
from os import listdir
from pyspark.ml.evaluation import BinaryClassificationEvaluator
\end{python}
\subsubsection{初始化环境}
SparkContext是在写Spark程序时入口用来连接Spark并进行后续的操作一般还会结合SparkConf对象来设置对Saprk集群的配置。这里我们用默认的设置即可。
SQLContext用来创建DataFrame。
\begin{python}
sc = SparkContext(appName="PythonlogExample")
sqlContext = SQLContext(sc)
\end{python}
\subsubsection{加载数据}
用于训练的DataFrame中应该包含两列特征向量和类别。其中类别是数字1或者0.特征向量就是把32*32的矩阵转换成一个1024维的向量即可。load\_data函数接受一个表示训练样本的所在的目录的参数遍历该目录下所有的文件也就是样本从样本的名字解析出它的类别是0还是1从文件内容中读取特征向量。然后生成DataFrame数据并返回。
\begin{python}
def load_data(data_folder):
file_list=listdir(data_folder)
file_num=len(file_list)
datas = list()
file_num=len(file_list)
datas = list()
for i in range(file_num):
filename=file_list[i]
fr=open('%s/%s' %(data_folder,filename))
data_in_line = list()
for j in range(32):
\end{python}
\newpage
\begin{python}
line_str=fr.readline()
for k in range(32):
data_in_line.append(int(line_str[k]))
label = filename.split('.')[0].split("_")[0]
datas.append((float(label),Vectors.dense(data_in_line)))
return sqlContext.createDataFrame(datas,["label","features"])
\end{python}
\subsubsection{模型训练}
再加载完训练数据后即可用LogisticRegression来对其进行训练。新建LogisticRegression对象时可以指定一些参数我在这里制定了最大迭代数和正则化参数。调用LogisticRegression的fit函数即可生成相应的LogisticRegressionModel。
\begin{python}
train_df = load_data("train")
lr = LogisticRegression(maxIter=10, regParam=0.3)
lrModel = lr.fit(train_df)
\end{python}
\subsubsection{模型评估}
利用测试数据对训练得到的模型进行评估BinaryClassificationEvaluator用于评估二分类结果我最后利用它计算了一下该模型的正确率。
\begin{python}
test_df = load_data("test")
predictions = lrModel.transform(test_df)
evaluator = BinaryClassificationEvaluator(labelCol="label", rawPredictionCol="rawPrediction", metricName="areaUnderPR")
accuracy = evaluator.evaluate(predictions)
print("Test Error = %g " % (1.0 - accuracy))
\end{python}
\subsection{结果}
\subsection{算法分析}
\end{document}

BIN
areaUnderROC_0.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
areaUnderROC_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
areaUnderROC_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
setMaxIter.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
show_0.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
show_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
show_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
statics.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -47,7 +47,7 @@ SystemML & 66 & 289 & 109 \\
\caption{各个系统在github上的关注度}
\end{table}
从上表可以看出关注度最高的是Tensforflow其次是MLlib无论是Star数还是fork数都是遥遥领先于其他几个系统。如此高的关注度说明了这两个系统得到了开发人员的广泛认可和支持。在我看来这就形成了一个如下图所示的“开源软件开发良性循环”一个项目质量高那么用户和开发者就越喜欢从而就会积极地去贡献自己的力量也就会促使该项目的质量进一步提高如此循环不断。当然TensorFlow本身质量高之外和Google在业内的影响力也分不开。我最看好的是MLlib因为现在它是Spark原生集成的库对运行在Sark上有先天的优势借着Sark的势头应该会得到更加迅猛的发展和应用。
从上表可以看出关注度最高的是Tensforflow其次是MLlib无论是Star数还是fork数都是遥遥领先于其他几个系统。如此高的关注度说明了这两个系统得到了开发人员的广泛认可和支持。在我看来这就形成了一个如下图所示的“开源软件开发良性循环”一个项目质量高那么用户和开发者就越喜欢从而就会积极地去贡献自己的力量也就会促使该项目的质量进一步提高如此循环不断。当然TensorFlow本身质量高之外和Google在业内的影响力也分不开。我最看好的是MLlib因为现在它是Spark原生集成的库对运行在Sark上有先天的优势借着Sark的势头应该会得到更加迅猛的发展和应用再加一些Spar今年峰会概况】
\begin{figure}[h!]
\centering

View File

@ -0,0 +1,301 @@
\documentclass[a4paper,12pt,UTF8,titlepage]{ctexart}
%页边距
\usepackage{geometry}
\geometry{left=2.0cm,right=2.0cm,top=2.5cm,bottom=2.5cm}
%页眉
\usepackage{fancyhdr}
\pagestyle{fancy}
\lhead{李志星 15060025 }
\chead{Spark MLlib应用报告}
\rhead{\leftmark}
%文档信息/同时也用于生成报告封面
\author{李志星\\ 15060025}
\title{\Huge MLlib中Logistic Regression的应用}
\usepackage{graphicx}
\usepackage{subfigure}
\DeclareGraphicsExtensions{.eps,.ps,.jpg,.bmp,.gif,.png}
\usepackage{pythonhighlight}
% "define" Scala
\usepackage{listings}
\lstdefinelanguage{scala}{
morekeywords={abstract,case,catch,class,def,%
do,else,extends,false,final,finally,%
for,if,implicit,import,match,mixin,%
new,null,object,override,package,%
private,protected,requires,return,sealed,%
super,this,throw,trait,true,try,%
type,val,var,while,with,yield},
otherkeywords={=>,<-,<\%,<:,>:,\#,@},
sensitive=true,
morecomment=[l]{//},
morecomment=[n]{},
morestring=[b]",
morestring=[b]',
morestring=[b]"""
}
\usepackage{color}
\definecolor{dkgreen}{rgb}{0,0.6,0}
\definecolor{gray}{rgb}{0.5,0.5,0.5}
\definecolor{mauve}{rgb}{0.58,0,0.82}
% Default settings for code listings
\lstset{frame=tb,
language=scala,
aboveskip=3mm,
belowskip=3mm,
showstringspaces=false,
columns=flexible,
basicstyle={\small\ttfamily},
numbers=none,
numberstyle=\tiny\color{gray},
keywordstyle=\color{blue},
commentstyle=\color{dkgreen},
stringstyle=\color{mauve},
frame=single,
breaklines=true,
breakatwhitespace=true
tabsize=3
}
\begin{document}
\maketitle
\section{前言}
\subsection{手写识别}
手写识别Handwriting recognition是计算机在纸、照片、触摸屏或其他设备中接收并识别人手写的文字等信息的技术主要应用于光学字符识别OCR。手写识别系统能够用来识别汉字、英语、数字等字符。不过本报告的重点不在手写识别而在于理解MLlib中的机器学习算法因此以识别数字为例。识别数字09是个十类别问题分类算法中最常用的场景是二分类如果要用二分类解决这个问题要采用one-against-one和one-against-all等做法进行处理虽然复杂些但是基本原理是一样的。因此本报告把主要关注点放在对MLlib算法的研究只利用0和1的样本从而解决二分类问题。
\subsection{Logistic Regression}
在Zaharia提出Spark的论文中他使用了Logistic Regression来作为一个实例来展示介绍Spark因此在本报告中我也利用Logistic Regression来解决手写识别问题。其实在本质上Logistic Regression是个线性回归它只不过是在特征到结果的映射过程中多加了一个二值函数映射即先把样本的特征线性求和接着把该连续值映射到0和1上。其大致的思路如下图所示
\begin{figure}[h!]
\centering
\includegraphics[width=8cm]{LG_arch.png}
\caption{Logistic Regression示意图}
\label{LG_arch}
\end{figure}
\subsection{MLlib算法主要机制}
在MLlib中有许多的概念其中对理解其算法比较重要的有\emph{DataFrame}\emph{Pipeline}\emph{Transfromer}\emph{Estimator}
\begin{itemize}
\item DataFrameMLlib使用SaprkSQL中DataFrame来操作数据集是最近才添加的API。在MLLib模块中有两个包都可以用来调用机器学习算法mllib和ml。mllibRDD操作而ml基于DataFrameml是官方推荐使用的。通过\emph{DataFrame}可以操作各种各样的数据:文本、图像和结构化数据等。\emph{DataFrame}以命名列的方式组织的分布式数据集 等同于关系型数据库中的一个表和R/Python中的\emph{DataFrame}类似,不过进行了很多的优化。
\item Pipeline在MLlib中有一个很关键的概念\emph{Pipeline}。在利用解决机器学习问题时经常要用对数据进行一系列的处理MLlib用\emph{Pipeline}来表示这样的工作流,在\emph{Pipeline}中,包含一组以一定顺序执行的\emph{ PipelineStage}( \emph{Transformer}\emph{Estimator})。
\item TransformerTransformer是对特征转换和学习得到的模型的抽象每一个\emph{Transfromer}都要实现transform()方法,它把一个\emph{DataFrame}处理后得到另一个\emph{DataFrame},一般来说新的DataFrame比原来的DataFrame要多一些列。
\item EstimatorEstimator是对一些机器学习算法或者其他的数据处理算法的抽象每一个\emph{Estimator}都有一个方法fit(),它以\emph{DataFrame}为参数,返回一个模型,也就是\emph{Transformer}比如在MLlib中 LogisticRegression 就是一个\emph{Estimator}而LogisticRegressionModel就是一个\emph{Transformer}
\end{itemize}
一个比较简单形象的例子就是文本文档的处理,如下图*所示,上面一行表示了一个包含3个stage的Pipeline前两个Tokenizer和HashingTF是Transformer,第三个LogisticRegression是一个Estimer。下面一行是一个流经pipeline的数据流,圆柱体代表了DataFrame.当调用pipeline的fit方法时 Tokenizer.transform() 把原始的Raw text切分成单词然后把这些单词添加到原DataFrame中形成新的DataFrame从而让HashingTF.transfore()进行处理他把单词列转化成特征矩阵又添加到新的DataFrame中最后通过 LogisticRegression.fit()方法产生LogisticRegressionModel。生成的模型可以用于后续的测试等。
\begin{figure}[h!]
\centering
\includegraphics[width=16cm]{pipeline.jpg}
\caption{MLlib pipeline}
\label{pipeline}
\end{figure}
\section{解决方案}
\subsection{数据集}
本报告用到的数据集是我从网上搜集到的一个文本文件对应一个样本里面包含一个32*32的0/1矩阵矩阵中每一个点相当于手写图像处理后一个像素点的值如下图*。训练数据和测试数据中分别有300和76个样本。
\begin{figure}[h!]
\centering
\subfigure[数字0对应的一个样本]{
\label{0} %% label for first subfigure
\includegraphics[width=1.0in]{data_0.jpg}}
\hspace{0.2in}
\subfigure[数字1对应的一个样本]{
\label{1} %% label for second subfigure
\includegraphics[width=1.0in]{data_1.jpg}}
\caption{样本示例}
\label{0_1} %% label for entire figure
\end{figure}
\subsection{代码}
如前言中所述MLlib中有两个用于机器学习的包mllib和ml根据应用趋势和其官方网站的建议我采用了ml。Spark本身使用Scala语言编写的但是它同样为Java、Python和R提供了几乎一致的接口在本次报告中我使用的python。详细代码见文件***.py。代码解释如下
\subsubsection{导入依赖}
此段代码导入需要用到的包包括数据处理的Vectors、算法训练的 LogisticRegression、算法评估BinaryClassificationEvaluator以及其他的一些用于和Spark操作的包。
\begin{python}
from pyspark import SparkContext
from pyspark.sql import SQLContext
from pyspark.ml.classification import LogisticRegression
from pyspark.mllib.linalg import Vectors
from os import listdir
from pyspark.ml.evaluation import BinaryClassificationEvaluator
\end{python}
\subsubsection{初始化环境}
SparkContext是在写Spark程序时入口用来连接Spark并进行后续的操作一般还会结合SparkConf对象来设置对Saprk集群的配置。这里我们用默认的设置即可。
SQLContext用来创建DataFrame。
\begin{python}
sc = SparkContext(appName="PythonlogExample")
sqlContext = SQLContext(sc)
\end{python}
\subsubsection{加载数据}
用于训练的DataFrame中应该包含两列特征向量和类别。其中类别是数字1或者0.特征向量就是把32*32的矩阵转换成一个1024维的向量即可。load\_data函数接受一个表示训练样本的所在的目录的参数遍历该目录下所有的文件也就是样本从样本的名字解析出它的类别是0还是1从文件内容中读取特征向量。然后生成DataFrame数据并返回。
\begin{python}
def load_data(data_folder):
file_list=listdir(data_folder)
file_num=len(file_list)
datas = list()
file_num=len(file_list)
datas = list()
for i in range(file_num):
filename=file_list[i]
fr=open('%s/%s' %(data_folder,filename))
data_in_line = list()
for j in range(32):
line_str=fr.readline()
for k in range(32):
data_in_line.append(int(line_str[k]))
label = filename.split('.')[0].split("_")[0]
datas.append((float(label),Vectors.dense(data_in_line)))
return sqlContext.createDataFrame(datas,["label","features"])
\end{python}
\subsubsection{模型训练}
再加载完训练数据后即可用LogisticRegression来对其进行训练。新建LogisticRegression对象时可以指定一些参数我在这里制定了最大迭代数和正则化参数。调用LogisticRegression的fit函数即可生成相应的LogisticRegressionModel。
\begin{python}
train_df = load_data("train")
lr = LogisticRegression(maxIter=10)
lrModel = lr.fit(train_df)
\end{python}
\subsubsection{模型评估}
利用测试数据对训练得到的模型进行评估BinaryClassificationEvaluator用于评估二分类结果我最后利用其提供的两个指标areaUnderROC和areaUnderPR中的areaUnderROC评价了一下该模型。areaUnderROC是ROC曲线右下角部分占正方形格子的面积比例该值越大说明分类的效果越好。
\newpage
\begin{python}
test_df = load_data("test")
predictions = lrModel.transform(test_df)
evaluator = BinaryClassificationEvaluator(labelCol="label", rawPredictionCol="rawPrediction", metricName="areaUnderPR")
accuracy=evaluator.evaluate(predictions)
print("Test Error = %g " % (1.0 - accuracy))
\end{python}
\subsection{结果}
在本次试验中我分别设置最大迭代次数为0,5,10来观察算法的训练效果。利用训练得到模型在测试数据上预测得到DataFrame predictions然后调用predictions的show()方法该方法会打印出前20个结果一共五列分别是label,features,rawPrediction,probability和prediction。label和features这两个列是加载的测试数据的类标号和特征向量。rawPrediction,probability和prediction是利用模型对测试数据进行预测得到的我查了一下相关文档rawPrediction和probability都是一个向量其维数就是类标号的个数rawPrediction字面上的意思是原始的预测直观的讲就是每个类的置信度confidence并且这个向量中的所有元素相加得到的和是0,probability是在给定rawPrediction的条件概率该样本属于每个类的可能性其计算方法根据所采用的分类算法而不同。在Logistic Regression中是这样计算的 1/(1+exp(-rawPrediction)。prediction是最后对样本的预测它是对rawPrediction利用argmax函数得到的也就是取对应rawPrediction最大的那个类。
\begin{itemize}
\item maxIter=0时算法给每个样本都预测为0这样就有一半的测试样本是错误的最后的areaUnderROC为0.5。\newline
\begin{figure}[h!]
\centering
\subfigure{
\label{0} %% label for first subfigure
\includegraphics[width=10cm]{show_0.jpg}}
\hspace{0.2in}
\subfigure{
\label{1} %% label for second subfigure
\includegraphics[width=8cm]{areaUnderROC_0.jpg}}
\caption{maxIter=0时预测值和areaUnderROC}
\label{0_1} %% label for entire figure
\end{figure}
\item maxIter=5时areaUnderROC为0.5。\newline
\begin{figure}[h!]
\centering
\subfigure{
\label{2} %% label for first subfigure
\includegraphics[width=10cm]{show_1.jpg}}
\hspace{0.2in}
\subfigure{
\label{3} %% label for second subfigure
\includegraphics[width=8cm]{areaUnderROC_1.jpg}}
\caption{maxIter=5时预测值和areaUnderROC}
\label{0_1} %% label for entire figure
\end{figure}
\item maxIter=10时areaUnderROC为0.5。\newline
\begin{figure}[h!]
\centering
\subfigure{
\label{4} %% label for first subfigure
\includegraphics[width=10cm]{show_2.jpg}}
\hspace{0.2in}
\subfigure{
\label{5} %% label for second subfigure
\includegraphics[width=8cm]{areaUnderROC_2.jpg}}
\caption{maxIter=10时预测值和areaUnderROC}
\label{0_1} %% label for entire figure
\end{figure}
\end{itemize}
从实验结果可以看出随着迭代次数的增加算法的效果也是越来越好。以rawPrediction或者probability为例样本取对的类标签的置信度或者概率随着迭代次数的增加不断增加。
\subsection{库源代码分析}
如前所述Spark 使用scala编写的其Java接口是直接调用的scala实现而Python接口又是基于Java接口实现的因此虽然我报告中使用的Python接口实现的但是算法的具体实现细节是用scala实现的由于本人未曾使用过scala因此在这里根据对代码的直观理解简要的介绍一下其大致思想。
\begin{itemize}
\item 参数设置,算法一开始都是一些基本的对参数的设置,比如迭代次数,规则化参数,是否对数据标准化等等。例如:
\begin{figure}[h!]
\centering
\includegraphics[width=16cm]{setMaxIter.jpg}
\caption{setMaxIter}
\label{setMaxIter}
\end{figure}
\item train()方法进行训练。\newline
首先是对训练数据集进行统计便于后续的处理。\newline
\newpage
\begin{lstlisting}[escapeinside='']
val (summarizer, labelSummarizer) = {
//'此处用于生成相应的统计数据'
}
val histogram = labelSummarizer.histogram
val numInvalid = labelSummarizer.countInvalid
val numClasses = histogram.length
val numFeatures = summarizer.mean.size
\end{lstlisting}
其次是对训练数据集进行一些有效性和特殊性的判断。\newline
\begin{lstlisting}
if (numClasses > 2) {
...
}
\end{lstlisting}
由于在Spark MLlib中ml版本中LogisticRegression还未支持多分类所以它会先判断样本是否是二分类否则会先报异常。如果想用多分类的话可以用mllib版本。我看了下mlib版本的源码它会进行判断如果是二分类它会调用ml版本的实现如果是多分类才会调用自己的实现。此外我发现Spark的帮助文档里有个小缺陷在ml关于LogisticRegression的介绍中他指出算法的详细实现细节可以看mllib的实现但是mllib的实现中关于二分类并没有具体的算法细节反而在ml的实现中是有的。
\begin{lstlisting}
} else if ($(fitIntercept) && numClasses == 2 && histogram(0) == 0.0) {
...
} else if ($(fitIntercept) && numClasses == 1) {
...
}
\end{lstlisting}
上面两个else分支是判断训练数据中的样本是否都是属于正样本否者负样本与此同时如果模型函数中还需要截距的话那么其实不需要进行训练了只要把系数都设为0然后把截距设为正无穷或者负无穷即可。
\begin{lstlisting}
if (!$(fitIntercept) && numClasses == 2 && histogram(0) == 0.0) {
...
} else if (!$(fitIntercept) && numClasses == 1) {
...
}
\end{lstlisting}
上面两段代码也是判断训练数据中的样本是否都是属于正样本否者负样本,但是模型函数中如果不需要截距的话,那么本次训练可能就会出现问题,所以它会进行警告。
\newpage
\begin{lstlisting}
if (!$(fitIntercept) && (0 until numFeatures).exists { i =>
featuresStd(i) == 0.0 && featuresMean(i) != 0.0 }) {
}
\end{lstlisting}
\end{itemize}
\end{document}

View File