from zengxiaosen
1,逻辑回归和多重线性回归的最大区别是因变量不同,其他基本差不多,因此两者同属于一个家族:广义线性模型。
这一家族中的模型形式基本差不多,不同的是因变量不同:
如果是连续的,就是多重线性回归;
如果是二项分布,就是逻辑回归;
如果是Poisson分布,就是Poisson回归;
如果是负二项分布,就是负二项回归。
逻辑回归主要的应用场景:
寻找危险因素:例如寻找某疾病的危险因素;
预测:根据模型预测不同的自变量情况下某病或某情况的发生概率;
判别:实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大可能是属于某病。
逻辑回归的常规步骤:
寻找H函数(假设函数);
构造J函数(损失函数);
想办法使得J函数最小并求得回归参数a
====
构造预测函数H:
逻辑回归是用于分类(主要用于二分类)问题;
它利用了Logistic函数(也叫作Sigmoid函数):
对于现行边界的情况,边界形式为:
所以构造预测函数为:
其中函数H(x)的值就是便是该变量x分类为类别1和0的概率分别为:
====
构造损失函数J:
====
利用梯度下降法求参数最小值:
正规化解决过度拟合......
2,在madlib上利用psql语句进行逻辑回归算法的应用:
所用到的思想就是利用标签数据训练一个模型,然后利用这个模型去预测病人第二次心脏病的发生。
第一步:
- DROP TABLE IF EXISTS patients, patients_logregr, patients_logregr_summary;
- CREATE TABLE patients( id INTEGER NOT NULL,
- second_attack INTEGER,
- treatment INTEGER,
- trait_anxiety INTEGER);
-
- INSERT INTO patients VALUES
- (1, 1, 1, 70),
- (3, 1, 1, 50),
- (5, 1, 0, 40),
- (7, 1, 0, 75),
- (9, 1, 0, 70),
- (11, 0, 1, 65),
- (13, 0, 1, 45),
- (15, 0, 1, 40),
- (17, 0, 0, 55),
- (19, 0, 0, 50),
- (2, 1, 1, 80),
- (4, 1, 0, 60),
- (6, 1, 0, 65),
- (8, 1, 0, 80),
- (10, 1, 0, 60),
- (12, 0, 1, 50),
- (14, 0, 1, 35),
- (16, 0, 1, 50),
- (18, 0, 0, 45),
- (20, 0, 0, 60);
在patients表中有四个元素:id,second_attack,treatment,trait_anxiety
第二步:
引用madlib的build_in功能,使用输入的训练数据训练一个分类模型:
- SELECT madlib.logregr_train(
- 'patients', -- source table
- 'patients_logregr', -- output table
- 'second_attack', -- labels
- 'ARRAY[1, treatment, trait_anxiety]', -- features
- NULL, -- grouping columns
- 20, -- max number of iteration
- 'irls' -- optimizer
- );
其中特征是treatment,trait_anxiety,因为要研究的是second_attack,所以把它作为labels,
输入的数据来自于patients表,训练后输出的数据会放在patients_logregr表,这里的迭代次数是20。
第三步骤:观察已经被训练完了的模型:
- -- Set extended display on for easier reading of output (\x is for psql only)
- \x on
- SELECT * from patients_logregr;
得到的结果是:
- -- ************ --
- -- Result --
- -- ************ --
- coef | [-6.36346994178187, -1.02410605239327, 0.119044916668606]
- log_likelihood | -9.41018298389
- std_err | [3.21389766375094, 1.17107844860319, 0.0549790458269309]
- z_stats | [-1.97998524145759, -0.874498248699549, 2.16527796868918]
- p_values | [0.0477051870698128, 0.38184697353045, 0.0303664045046168]
- odds_ratios | [0.0017233763092323, 0.359117354054954, 1.12642051220895]
- condition_no | 326.081922792
- num_rows_processed | 20
- num_missing_rows_skipped | 0
- num_iterations | 5
- variance_covariance | [[10.3291381930637, -0.47430466519573, -0.171995901260052], [-0.47430466519573, 1.37142473278285, -0.00119520703381598], [-0.171995901260052, -0.00119520703381598, 0.00302269548003977]]
-
这是训练完的结果,其中coef也就是coefficient,是系数的意思,log_likelihood是对应的似然,std_err是标准误差
- -- Alternatively, unnest the arrays in the results for easier reading of output (\x is for psql only)
- \x off
- SELECT unnest(array['intercept', 'treatment', 'trait_anxiety']) as attribute,
- unnest(coef) as coefficient,
- unnest(std_err) as standard_error,
- unnest(z_stats) as z_stat,
- unnest(p_values) as pvalue,
- unnest(odds_ratios) as odds_ratio
- FROM patients_logregr;
得到的结果是:
- -- ************ --
- -- Result --
- -- ************ --
- +---------------+---------------+------------------+-----------+-----------+--------------+
- | attribute | coefficient | standard_error | z_stat | pvalue | odds_ratio |
- |---------------+---------------+------------------+-----------+-----------+--------------|
- | intercept | -6.36347 | 3.2139 | -1.97999 | 0.0477052 | 0.00172338 |
- | treatment | -1.02411 | 1.17108 | -0.874498 | 0.381847 | 0.359117 |
- | trait_anxiety | 0.119045 | 0.054979 | 2.16528 | 0.0303664 | 1.12642 |
- +---------------+---------------+------------------+-----------+-----------+--------------+
第三步:
利用训练完的模型去预测,根据原始数据去产生预测值:
- -- Display prediction value along with the original value
- SELECT p.id, madlib.logregr_predict(coef, ARRAY[1, treatment, trait_anxiety]),
- p.second_attack
- FROM patients p, patients_logregr m
- ORDER BY p.id;
select的第一个参数是病人的id,第二个参数是madlib根据coef系数以及特征数组进行逻辑回归预测所产生的true或者是false,第三个参数是病人实际第二次心脏病发生与否,以下是结果:
- -- ************ --
- -- Result --
- -- ************ --
- +------+-------------------+-----------------+
- | id | logregr_predict | second_attack |
- |------+-------------------+-----------------|
- | 1 | True | 1 |
- | 2 | True | 1 |
- | 3 | False | 1 |
- | 4 | True | 1 |
- | 5 | False | 1 |
- | 6 | True | 1 |
- | 7 | True | 1 |
- | 8 | True | 1 |
- | 9 | True | 1 |
- | 10 | True | 1 |
- | 11 | True | 0 |
- | 12 | False | 0 |
- | 13 | False | 0 |
- | 14 | False | 0 |
- | 15 | False | 0 |
- | 16 | False | 0 |
- | 17 | True | 0 |
- | 18 | False | 0 |
- | 19 | False | 0 |
- | 20 | True | 0 |
- +------+-------------------+-----------------+
如果预测的可能性为true状态,就求出他发生这种预测的可能概率:
- SELECT p.id, madlib.logregr_predict_prob(coef, ARRAY[1, treatment, trait_anxiety])
- FROM patients p, patients_logregr m
- ORDER BY p.id;
select的第一个参数是病人的id,第二个参数是由coef系数以及有特征构成的数组得到的预测发生概率,结果是:
- -- ************ --
- -- Result --
- -- ************ --
- +------+------------------------+
- | id | logregr_predict_prob |
- |------+------------------------|
- | 1 | 0.720223 |
- | 2 | 0.894355 |
- | 3 | 0.19227 |
- | 4 | 0.685513 |
- | 5 | 0.167748 |
- | 6 | 0.798098 |
- | 7 | 0.928568 |
- | 8 | 0.959306 |
- | 9 | 0.877576 |
- | 10 | 0.685513 |
- | 11 | 0.586701 |
- | 12 | 0.19227 |
- | 13 | 0.116032 |
- | 14 | 0.0383829 |
- | 15 | 0.0674976 |
- | 16 | 0.19227 |
- | 17 | 0.545871 |
- | 18 | 0.267675 |
- | 19 | 0.398619 |
- | 20 | 0.685513 |
- +------+------------------------+
3,在sparkMLlib上面使用逻辑回归算法进行预测:
- package test
- import org.apache.avro.ipc.specific.Person
- import org.apache.spark.ml.classification.{LogisticRegression, LogisticRegressionModel}
- import org.apache.spark.mllib.classification.{LogisticRegressionWithLBFGS, LogisticRegressionWithSGD}
- import org.apache.spark.mllib.evaluation.MulticlassMetrics
- import org.apache.spark.mllib.linalg.Vectors
- import org.apache.spark.mllib.regression.LabeledPoint
- import org.apache.spark.{SparkConf, SparkContext}
- /**
- * Created by zengxiaosen on 16/6/6.
- */
- object sparksql_logisticregression {
- def main(args: Array[String]) {
- val conf=new SparkConf()
- conf.setAppName("Logistic_regression")
- conf.setMaster("local")
- val sc=new SparkContext(conf)
- val data = sc.textFile("/Users/zengxiaosen/test/people_0.txt")
- val parsedData = data.map { line => //开始对数据集处理
- val parts = line.split(',') //根据逗号进行分区
- LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(' ').map(_.toDouble)))
- } //转化数据格式
- parsedData.foreach(println)
- //val model=new LogisticRegressionWithLBFGS().setNumClasses(10).run(training)
- //划分一下训练数据和测试数据,将parsedData的60%分为训练数据,40%分为测试数据
- val splits = parsedData.randomSplit(Array(0.6, 0.4), seed = 11L)
- val trainingData = splits(0)
- val testData = splits(1)
- //运行训练算法构建模型:
- //val model_0=LogisticRegressionWithSGD.train(trainingData, 50)
- //运行训练算法构建模型
- val model = new LogisticRegressionWithLBFGS().setNumClasses(2).run(trainingData)
- //当模型训练完,我们可以使用testData来检验一下模型的出错率
- //变量labelAndPreds保存了map()转换操作,map()将每一个行转换成二元组。
- //二元组包含了testData的标签数据(point.label,分类数据)和预测出来的分类数据(prediction)。模型使用point.features作为输入数据。
- /*val labelAndPreds = testData.map { point =>
- val prediction = model.predict(point.features)
- (point.label, prediction)
- }*/
- val target = Vectors.dense(-1) //创建测试值
- val resulet = model.predict(target) //根据模型计算结果
- //println(labelAndPreds)
- //val trainErr = labelAndPreds.filter(r => r._1 != r._2).count.toDouble / testData.count
- //println(trainErr)
- println("model_weight:")
- println(model.weights)
- println(resulet) //打印结果
- println(model.predict(Vectors.dense(10)))
- sc.stop
- //获取评估指标
- //保存和加载模型
- }
- }
产生的结果:
总结:
1:madlib使得数据库中的表数据能够直接方便的做逻辑回归,通过简单的psql语句就能够挖掘和预测出有用的信息,而spark的机器学习库对于不懂spark的人来说不容易驾驭,因为它涉及各种RDD算子的transformation或者checkpoint等过程,而如果产生bug还需要查看集群的各种信息(包括进程线程容器资源管理器等),给只熟悉sql的人员带来极大负担,但是madlib的操作比较稳定,不太容易产生调试上的操作,当然如果你能驾驭spark,利用spark进行机器学习还是非常方便的;
2:如果利用madlib进行数据挖掘,必须把非关系型数据通过ETL整理成关系型数据进行分析学习,而spark很擅长非关系型数据的处理,所以在ETL阶段,需要想办法更加高效;
3:作为一个用户,在学习难度方面两者相当;
4:在成熟度方面,sparkecosy中的MLlib成熟度没有madlib高,greenplum和madlib都比较成熟;
5:在性能方面,由于spark做机器学习的过程中数据可以checkpoint,而madlib都是写磁盘的,所以在性能方面MLlib比较好。