Spark 多项逻辑回归的意外系数
Unexpected coefficients from Spark multinomial Logistic Regression
我 运行 我的 Mac、OS Sierra 上的 Spark 2.1.1(这应该有帮助)。我试图在我在网上找到的测试数据集上拟合多项逻辑回归,我在这里报告前几行(我不知道如何在此处附加文件):
1,0,24
1,0,26
1,0,26
1,1,27
1,1,27
3,1,27
第一列是标签('brand',值:1、2、3),第二列和第三列是特征('sex'和'age')。
由于标签有 3 个 class,多项式逻辑回归应该执行 3 个二项式模型,然后从其中 class 的概率最大的模型中选择预测。所以我希望模型 return 一个 3x2 系数矩阵:3 因为 classes 是 3,而 2 因为特征是 2。This 文档似乎与这个观点一致.
但是,惊喜惊喜...
>>> logit_model.coefficientMatrix
DenseMatrix(4, 2, [-1.2781, -2.8523, 0.0961, 0.5994, 0.6199, 0.9676, 0.5621, 1.2853], 1)
>>> logit_model.interceptVector
DenseVector([-4.5912, 13.0291, 1.2544, -9.6923])
系数矩阵是 4x2,我有 4 个截距而不是 3 个。更奇怪的是:
>>> logit_model.numClasses
4
出于某种奇怪的原因,模型 "feel" 4 classes,即使我只有 3 个(请参阅下面的代码来检查)。
有什么建议吗?
非常感谢。
完整代码如下:
from pyspark.sql import functions as f
from pyspark.sql import types as t
from pyspark.ml import classification as cl
from pyspark.ml import feature as feat
customSchema = t.StructType(
[t.StructField('brand', t.IntegerType(), True),
t.StructField('sex', t.IntegerType(), True),
t.StructField('age', t.IntegerType(), True)]
)
test_df01 = (
spark
.read
.format('csv')
.options(delimiter=',', header=False)
.load('/Users/vanni/Downloads/mlogit_test.csv', schema=customSchema)
)
va = (
feat.VectorAssembler()
.setInputCols(['sex', 'age'])
.setOutputCol('features')
)
test_df03 = (
va
.transform(test_df01)
.drop('sex')
.drop('age')
.withColumnRenamed('brand', 'label')
)
logit_abst = (
cl.LogisticRegression()
.setFamily('multinomial')
.setStandardization(False)
.setThresholds([.5, .5, .5]) # to be adjusted after I know the actual values
.setThreshold(None)
.setMaxIter(100) # default
.setRegParam(0.0) # default
.setElasticNetParam(0.0) # default
.setTol(1e-6) # default
)
logit_model = logit_abst.fit(test_df03)
这里是 classes 只是 3 的检查:
>>> test_df03.select('label').distinct().orderBy('label').show()
+-----+
|label|
+-----+
| 1|
| 2|
| 3|
+-----+
这里没有什么奇怪的事情发生。 Spark 假定标签是连续的整数值,表示为 DoubleType
,并以 0.
开头
由于您获得的最大标签是 3,因此 Spark 假定标签实际上是 0、1、2、3 - 即使 0 从未出现在数据集中。
如果不希望出现这种行为,您应该将标签重新编码为从零开始,或者在原始标签上应用 StringIndexer
。
我 运行 我的 Mac、OS Sierra 上的 Spark 2.1.1(这应该有帮助)。我试图在我在网上找到的测试数据集上拟合多项逻辑回归,我在这里报告前几行(我不知道如何在此处附加文件):
1,0,24
1,0,26
1,0,26
1,1,27
1,1,27
3,1,27
第一列是标签('brand',值:1、2、3),第二列和第三列是特征('sex'和'age')。
由于标签有 3 个 class,多项式逻辑回归应该执行 3 个二项式模型,然后从其中 class 的概率最大的模型中选择预测。所以我希望模型 return 一个 3x2 系数矩阵:3 因为 classes 是 3,而 2 因为特征是 2。This 文档似乎与这个观点一致.
但是,惊喜惊喜...
>>> logit_model.coefficientMatrix
DenseMatrix(4, 2, [-1.2781, -2.8523, 0.0961, 0.5994, 0.6199, 0.9676, 0.5621, 1.2853], 1)
>>> logit_model.interceptVector
DenseVector([-4.5912, 13.0291, 1.2544, -9.6923])
系数矩阵是 4x2,我有 4 个截距而不是 3 个。更奇怪的是:
>>> logit_model.numClasses
4
出于某种奇怪的原因,模型 "feel" 4 classes,即使我只有 3 个(请参阅下面的代码来检查)。
有什么建议吗? 非常感谢。
完整代码如下:
from pyspark.sql import functions as f
from pyspark.sql import types as t
from pyspark.ml import classification as cl
from pyspark.ml import feature as feat
customSchema = t.StructType(
[t.StructField('brand', t.IntegerType(), True),
t.StructField('sex', t.IntegerType(), True),
t.StructField('age', t.IntegerType(), True)]
)
test_df01 = (
spark
.read
.format('csv')
.options(delimiter=',', header=False)
.load('/Users/vanni/Downloads/mlogit_test.csv', schema=customSchema)
)
va = (
feat.VectorAssembler()
.setInputCols(['sex', 'age'])
.setOutputCol('features')
)
test_df03 = (
va
.transform(test_df01)
.drop('sex')
.drop('age')
.withColumnRenamed('brand', 'label')
)
logit_abst = (
cl.LogisticRegression()
.setFamily('multinomial')
.setStandardization(False)
.setThresholds([.5, .5, .5]) # to be adjusted after I know the actual values
.setThreshold(None)
.setMaxIter(100) # default
.setRegParam(0.0) # default
.setElasticNetParam(0.0) # default
.setTol(1e-6) # default
)
logit_model = logit_abst.fit(test_df03)
这里是 classes 只是 3 的检查:
>>> test_df03.select('label').distinct().orderBy('label').show()
+-----+
|label|
+-----+
| 1|
| 2|
| 3|
+-----+
这里没有什么奇怪的事情发生。 Spark 假定标签是连续的整数值,表示为 DoubleType
,并以 0.
由于您获得的最大标签是 3,因此 Spark 假定标签实际上是 0、1、2、3 - 即使 0 从未出现在数据集中。
如果不希望出现这种行为,您应该将标签重新编码为从零开始,或者在原始标签上应用 StringIndexer
。