47、基于逻辑回归的二手车分类:从数据测试到边界决策

基于逻辑回归的二手车分类:从数据测试到边界决策

1. 真实数据上的分类函数测试

在进行分类函数测试前,我们需要先加载汽车数据。为了简化操作,提供了一个名为 car_data.py 的 Python 文件,其中包含了宝马(BMW)和普锐斯(Prius)的数据数组。我们可以通过以下方式导入这些数据:

from car_data import bmws, priuses

查看 car_data.py 中的原始数据,会发现其中包含了比我们所需更多的信息。目前,我们主要关注每辆车的里程数和价格,并且根据数据所属列表来确定车辆类型。例如,宝马的数据列表开头如下:

[('bmw', '5', 2013.0, 93404.0, 13999.0, 22.09145859494213),
 ('bmw', '5', 2013.0, 110890.0, 13995.0, 22.216458611342592),
 ('bmw', '5', 2013.0, 94133.0, 13982.0, 22.09145862741898),
 ...

每个元组代表一辆待售汽车,里程数和价格分别是元组的第四个和第五个元素。在 car_data.py 中,这些数据被转换为 Car 对象,这样我们可以使用 car.price 而不是 car[4] 来访问价格。我们可以从宝马和普锐斯的元组中提取所需信息,创建一个名为 all_car_data 的列表:

all_car_data = []
for bmw in bmws:
    all_car_data.append((bmw.mileage, bmw.price, 1))
for prius in priuses:
    all_car_data.append((prius.mileage, prius.price, 0))

运行上述代码后, all_car_data 是一个 Python 列表,开头是宝马的数据,结尾是普锐斯的数据,分别用 1 和 0 进行标记:

[(93404.0, 13999.0, 1),
 (110890.0, 13995.0, 1),
 (94133.0, 13982.0, 1),
 (46778.0, 14599.0, 1),
 ...
(45000.0, 16900.0, 0),
(38000.0, 13500.0, 0),
(71000.0, 12500.0, 0)]
1.1 测试分类函数

有了合适格式的数据后,我们可以编写 test_classifier 函数。 bmw_finder 函数的任务是根据汽车的里程数和价格判断是否为宝马。如果是,返回 1;否则返回 0。 bmw_finder 可能会出现判断错误的情况:
- 若预测为宝马(返回 1),但实际是普锐斯,这称为假阳性。
- 若预测为普锐斯(返回 0),但实际是宝马,这称为假阴性。
- 若正确识别为宝马或普锐斯,则分别称为真阳性或真阴性。

以下是测试分类函数的代码:

def test_classifier(classifier, data):
    trues = 0
    falses = 0
    for mileage, price, is_bmw in data:
        if classifier(mileage, price) == is_bmw:
            trues += 1
        else:
            falses += 1
    return trues / (trues + falses)

使用 bmw_finder 分类函数和 all_car_data 数据集运行此函数,发现其准确率为 59%:

>>> test_classifier(bmw_finder, all_car_data)
0.59

虽然这个结果还不错,但我们可以做得更好。接下来,我们将通过绘制数据集来分析 bmw_finder 函数存在的问题,以便使用逻辑分类函数改进分类效果。

1.2 练习题解答
  • 练习 15.1 :更新 test_classifier 函数,打印真阳性、真阴性、假阳性和假阴性的数量。通过打印 bmw_finder 分类器的这些数据,我们可以了解该分类器的性能。
def test_classifier(classifier, data, verbose=False):
    true_positives = 0
    true_negatives = 0
    false_positives = 0
    false_negatives = 0
    for mileage, price, is_bmw in data:
        predicted = classifier(mileage, price)
        if predicted and is_bmw:
            true_positives += 1
        elif predicted:
            false_positives += 1
        elif is_bmw:
            false_negatives += 1
        else:
            true_negatives += 1
    if verbose:
        print("true positives %f" % true_positives)
        print("true negatives %f" % true_negatives)
        print("false positives %f" % false_positives)
        print("false negatives %f" % false_negatives)
    total = true_positives + true_negatives
    return total / len(data)

对于 bmw_finder 函数,打印结果如下:

true positives 18.000000
true negatives 100.000000
false positives 0.000000
false negatives 82.000000

由于该分类器没有假阳性,说明它总能正确识别非宝马的汽车。但它将大多数汽车都判断为非宝马,包括很多实际上是宝马的汽车,因此不能对这个函数过于满意。在接下来的练习中,我们可以放宽限制以提高整体成功率。
- 练习 15.2 :找到一种方法更新 bmw_finder 函数以提高其性能,并使用 test_classifier 函数确认改进后的函数准确率超过 59%。

def bmw_finder2(mileage, price):
    if price > 20000:
        return 1
    else:
        return 0

通过降低价格阈值到 20000 美元, bmw_finder2 的成功率提高到了 73.5%:

>>> test_classifier(bmw_finder2, all_car_data)
0.735
2. 可视化决策边界

在实现逻辑回归函数之前,我们可以通过另一种方式衡量分类的成功程度。由于二手车数据点由里程数和价格两个数值定义,我们可以将它们视为二维向量,并在二维平面上绘制这些点。这样的绘图可以让我们更清楚地看到分类函数在宝马和普锐斯之间“划清界限”的位置,从而找到改进的方法。

2.1 可视化汽车空间

数据集中的所有汽车都有里程数和价格值,根据标记的 1 或 0 分别代表宝马或普锐斯。为了使散点图更易读,我们希望在图中直观地区分宝马和普锐斯。源代码中的 plot_data 辅助函数可以自动将宝马用 X 表示,普锐斯用圆圈表示进行绘图:

>>> plot_data(all_car_data)

从图中可以看出,一般来说宝马比普锐斯更贵,大多数宝马在价格轴上的位置更高。这也证明了我们将较贵的汽车分类为宝马的策略是合理的。具体来说,我们在价格为 25000 美元处画了一条线,这条线将图的上部(较贵的汽车)和下部(较便宜的汽车)分开,这就是我们的决策边界。线上方的 X 被正确识别为宝马,线下方的圆圈被正确识别为普锐斯,其他点则被错误分类。显然,移动这条决策边界可以提高我们的准确率。

2.2 绘制更好的决策边界

根据之前的绘图,我们可以降低这条线的位置,从而正确识别更多的宝马,同时不会错误识别普锐斯。例如,将截止价格降低到 21000 美元,这对于低里程数的汽车可能是一个不错的边界。但随着里程数的增加,阈值应该降低。为了模拟这种情况,我们可以使截止价格与里程数相关,从几何角度看,这意味着绘制一条向下倾斜的线,其函数为 p(x) = 21000 - 0.07 * x (其中 p 是价格, x 是里程数)。这条线似乎能正确识别更多的宝马,只有少数假阳性(普锐斯被错误分类为宝马)。

2.3 实现分类函数

为了将这个决策边界转换为分类函数,我们需要编写一个 Python 函数,根据汽车的里程数和价格判断该点是在线上方还是下方,从而返回 1 或 0:

def decision_boundary_classify(mileage, price):
    if price > 21000 - 0.07 * mileage:
        return 1
    else:
        return 0

测试这个函数,发现它比第一个分类器要好得多,准确率达到了 80.5%:

>>> test_classifier(decision_boundary_classify, all_car_data)
0.805

你可能会问,为什么不直接对决策边界线的参数进行梯度下降。实际上,当我们实现逻辑回归时,它会在底层使用梯度下降移动决策边界,直到找到最佳边界。但我们选择实现更复杂的逻辑回归算法而不是直接对决策边界函数 ax + b 的参数 a b 进行梯度下降,主要有两个原因:
- 如果决策边界在梯度下降的任何步骤接近垂直, a b 的值可能会变得非常大,从而导致数值问题。
- 没有明显的成本函数。

2.4 练习题解答
  • 练习 15.3(迷你项目) :找到形式为 p = 常数 的决策边界,使其在测试数据集上具有最佳的分类准确率。
def constant_price_classifier(cutoff_price):
    def c(x, p):
        if p > cutoff_price:
            return 1
        else:
            return 0
    return c

def cutoff_accuracy(cutoff_price):
    c = constant_price_classifier(cutoff_price)
    return test_classifier(c, all_car_data)

>>> max(all_prices, key=cutoff_accuracy)
17998.0

这表明根据数据集,17998 美元是判断汽车是宝马 5 系还是普锐斯的最佳价格阈值,其准确率达到了 79.5%:

>>> test_classifier(constant_price_classifier(17998.0), all_car_data)
0.795
3. 将分类问题转化为回归问题

我们可以将分类任务重新构建为回归问题,方法是创建一个函数,该函数接受汽车的里程数和价格,并返回一个数值,表示该汽车是宝马而非普锐斯的可能性。在这部分,我们将实现一个名为 logistic_classifier 的函数,从外部看,它与我们之前构建的分类器很相似,接受里程数和价格作为输入,并输出一个数值表示汽车是宝马的可能性,但输出值在 0 到 1 之间。

3.1 缩放原始汽车数据

在回归过程中,我们需要处理一个问题:里程数和价格的较大值可能会导致数值错误,因此最好将它们线性缩放到 0 到 1 之间的较小、一致的大小。我们需要四个函数来实现里程数和价格的缩放与反缩放,为了简化操作,提供了一个辅助函数:

def make_scale(data):
    min_val = min(data)
    max_val = max(data)
    def scale(x):
        return (x - min_val) / (max_val - min_val)
    def unscale(y):
        return y * (max_val - min_val) + min_val
    return scale, unscale

price_scale, price_unscale = make_scale([x[1] for x in all_car_data])
mileage_scale, mileage_unscale = make_scale([x[0] for x in all_car_data])

scaled_car_data = [(mileage_scale(mileage), price_scale(price), is_bmw)
                   for mileage, price, is_bmw in all_car_data]

缩放后的数据集绘图与之前类似,只是坐标轴上的值不同,但这样可以降低数值错误的风险。

以下是整个流程的 mermaid 流程图:

graph LR
    A[加载汽车数据] --> B[构建 all_car_data 列表]
    B --> C[测试分类函数]
    C --> D[可视化决策边界]
    D --> E[绘制更好的决策边界]
    E --> F[实现分类函数]
    F --> G[将分类问题转化为回归问题]
    G --> H[缩放原始汽车数据]

综上所述,通过对二手车数据的处理、分类函数的测试、决策边界的可视化和调整,以及将分类问题转化为回归问题并进行数据缩放,我们逐步提高了汽车分类的准确率。在实际应用中,我们可以根据具体需求进一步优化分类模型,以获得更好的效果。

基于逻辑回归的二手车分类:从数据测试到边界决策

4. 构建逻辑分类器

我们已经了解了如何测试分类函数、可视化决策边界以及将分类问题转化为回归问题。接下来,我们将构建逻辑分类器 logistic_classifier ,它能输出一个介于 0 到 1 之间的值,表示汽车是宝马的可能性。

4.1 逻辑分类器的原理

逻辑分类器基于一个初始的决策边界线。位于决策边界线上方的点具有较高的“宝马性”,意味着这些点很可能代表宝马,逻辑函数应返回接近 1 的值;而位于决策边界线下方的点“宝马性”较低,更可能是普锐斯,函数应返回接近 0 的值。在决策边界上,“宝马性”值为 0.5,表示该数据点是宝马和普锐斯的可能性相等。

4.2 实现逻辑分类器

虽然文中未给出完整的逻辑分类器实现代码,但我们可以根据之前的决策边界函数和数据缩放的思路来初步构建一个简单的逻辑分类器示例。假设我们使用之前得到的决策边界函数 p(x) = 21000 - 0.07 * x 作为基础:

def logistic_classifier(mileage, price):
    scaled_mileage = mileage_scale(mileage)
    scaled_price = price_scale(price)
    threshold = price_scale(21000 - 0.07 * mileage_unscale(scaled_mileage))
    if scaled_price > threshold:
        return 0.8  # 这里简单假设上方为 0.8,实际需要更复杂的逻辑
    else:
        return 0.2  # 这里简单假设下方为 0.2,实际需要更复杂的逻辑

需要注意的是,上述代码只是一个简单示例,实际的逻辑分类器需要更复杂的逻辑和数学模型来准确计算汽车是宝马的可能性。

4.3 测试逻辑分类器

使用之前的 test_classifier 函数来测试逻辑分类器的性能:

>>> test_classifier(logistic_classifier, scaled_car_data)
# 这里会输出逻辑分类器的准确率,具体数值取决于实际的实现和数据
5. 分类器性能的综合评估

在前面的内容中,我们通过不同的方法和函数来评估分类器的性能,如计算准确率、统计真阳性、真阴性、假阳性和假阴性等。下面我们将对不同分类器的性能进行综合比较。

分类器 准确率 特点
bmw_finder 59% 简单判断,但准确率较低,将多数车判断为非宝马
bmw_finder2 73.5% 通过降低价格阈值提高了准确率
decision_boundary_classify 80.5% 考虑了里程数和价格的关系,准确率较高
constant_price_classifier(17998.0) 79.5% 以固定价格为阈值,有较高的准确率
logistic_classifier(示例) 待确定 输出可能性值,理论上能更准确地分类

从表格中可以看出,不同的分类器在准确率和特点上有所不同。在实际应用中,我们可以根据具体需求选择合适的分类器。

6. 总结与展望

通过对二手车数据的处理和分析,我们从简单的分类函数测试开始,逐步深入到决策边界的可视化、分类问题的转化以及逻辑分类器的构建。整个过程中,我们不断优化分类器的性能,提高了汽车分类的准确率。

在未来的工作中,我们可以进一步优化逻辑分类器的实现,使用更复杂的数学模型和算法来提高分类的准确性。例如,可以引入更多的特征变量,如汽车的年份、配置等,以更全面地描述汽车的特征。同时,我们还可以使用交叉验证等方法来评估和选择最佳的分类模型,避免过拟合和欠拟合的问题。

以下是优化和改进的步骤列表:
1. 收集更多的汽车特征数据,如年份、配置等。
2. 对新的特征数据进行预处理,包括缩放、归一化等操作。
3. 构建更复杂的逻辑分类器模型,如使用逻辑回归算法的标准实现。
4. 使用交叉验证方法评估不同模型的性能,选择最佳模型。
5. 对最佳模型进行调优,调整模型的参数以提高准确率。

以下是未来优化流程的 mermaid 流程图:

graph LR
    A[收集更多特征数据] --> B[预处理特征数据]
    B --> C[构建复杂逻辑分类器模型]
    C --> D[交叉验证评估模型]
    D --> E[选择最佳模型]
    E --> F[调优最佳模型]

总之,通过不断地探索和实践,我们可以构建出更准确、更可靠的汽车分类模型,为二手车市场的分析和决策提供有力的支持。

基于遗传算法的微电网调度(风、光、蓄电池、微型燃气轮机)(Matlab代码实现)内容概要:本文档介绍了基于遗传算法的微电网调度模型,涵盖风能、太阳能、蓄电池和微型燃气轮机等多种能源形式,并通过Matlab代码实现系统优化调度。该模型旨在解决微电网中多能源协调运行的问题,优化能源分配,降低运行成本,提高可再生能源利用率,同时考虑系统稳定性与经济性。文中详细阐述了遗传算法在求解微电网多目标优化问题中的应用,包括编码方式、适应度函数设计、约束处理及算法流程,并提供了完整的仿真代码供复现与学习。此外,文档还列举了大量相关电力系统优化案例,如负荷预测、储能配置、潮流计算等,展示了广泛的应用背景和技术支撑。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事微电网、智能电网优化研究的工程技术人员。; 使用场景及目标:①学习遗传算法在微电网调度中的具体实现方法;②掌握多能源系统建模与优化调度的技术路线;③为科研项目、毕业设计或实际工程提供可复用的代码框架与算法参考; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注目标函数构建与约束条件处理,同时可参考文档中提供的其他优化案例进行拓展学习,以提升综合应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值