第十八篇 python(4)-多进程

协程、线程与进程

协程、线程和进程是计算机编程中常用的并发编程概念。总的来说,协程适合于高并发、I/O 密集型的场景,可以减少线程切换的开销;线程适合于 CPU 密集型和需要实时响应的任务;而进程则适合于独立性强、资源隔离要求高的任务。在实际应用中,通常会根据任务的特点和需求选择合适的并发编程模型。

协程

协程是一种程序组件,类似于线程,但其执行过程是可中断的。
在协程中,执行可以在特定的位置暂停,并在需要时恢复。
协程通常在单个线程中运行,因此不涉及线程切换的开销,可以有效地利用系统资源。

线程

线程是操作系统能够进行运算调度的最小单位。
一个进程中可以包含多个线程,它们共享进程的内存空间和其他资源。
多线程编程允许程序同时执行多个任务,提高了程序的并发性和响应性。
线程之间的切换开销相对较小,但线程间的共享资源需要进行同步,以避免竞态条件和死锁等问题

进程

进程是程序执行时的一个实例,每个进程都有自己独立的内存空间和系统资源。
进程间相互独立,各自拥有独立的地址空间和资源,彼此之间通信需要特殊的机制。
多进程编程可以充分利用多核处理器,但进程间的切换开销相对较大,因为需要切换地址空间和资源上下文。

python如何使用协程、线程与进程

在Python中,可以使用不同的工具来实现协程、线程和进程。
在Python中,协程通常使用 asyncio 库来实现。 线程可以使用内置的 threading 模块来实现。进程可以使用 multiprocessing 模块来实现。
需要注意的是,在Python中,由于全局解释器锁(GIL)的存在,多线程并不能有效利用多核处理器。因此,如果需要充分利用多核处理器,可以考虑使用多进程。而协程则是在单个线程中实现并发的一种方式,适合于I/O密集型任务。

第十七篇 强化学习(1)-马尔可夫决策过程

马尔可夫决策过程

马尔可夫性质:当前状态可以完全表征过程。

对于任意有限的马尔可夫决策过程,都存在一个最优策略,不差于其他所有可能的策略。

贝尔曼方程

第十六篇 python(3)-matplotlib绘图

安装

1
2
pip install matplotlib

简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt

# 数据
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]

# 绘图
plt.plot(x, y)

# 添加标题和标签
plt.title('Simple Line Plot')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')

# 显示图形
plt.show()

更多例子

多个子图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import matplotlib.pyplot as plt
import numpy as np

# 数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 创建一个包含两个子图的图形
fig, (ax1, ax2) = plt.subplots(2, 1)

# 在第一个子图中绘制正弦函数
ax1.plot(x, y1, 'r-')
ax1.set_title('Sine Function')
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')

# 在第二个子图中绘制余弦函数
ax2.plot(x, y2, 'g--')
ax2.set_title('Cosine Function')
ax2.set_xlabel('X-axis')
ax2.set_ylabel('Y-axis')

# 设置图形的整体标题
plt.suptitle('Sine and Cosine Functions')

# 自定义图形的风格
plt.style.use('ggplot')

# 调整子图的间距
plt.tight_layout()

# 显示图形
plt.show()

第十五篇 机器学习(4)-决策树

决策树

决策树是一种用于分类和回归问题的监督学习算法。它通过树状图的结构来表示和推断决策规则。每个内部节点表示一个特征或属性,每个分支代表一个决策规则,而每个叶节点表示一个类别标签或一个数值。

决策树的学习过程形成了一个递归的分治算法,其中每个节点都对应于一个特征,并且通过节点上的决策规则将数据集分割成更纯的子集。在决策树的构建过程中,选择最佳特征和分割数据的目标是提高每个节点的纯度,使得决策树在训练数据上达到最佳的拟合效果。

第十四篇 机器学习(3)-支持向量机

支持向量机

支持向量机(Support Vector Machine,SVM)是一种用于分类和回归分析的监督学习算法。它的主要目标是找到一个超平面,将数据集划分成两个类别,同时使得两个类别中距离最近的数据点到该超平面的距离最大化。这两个最近的数据点被称为支持向量。

SVM 可以使用核函数来处理非线性可分的数据。核函数可以将输入特征映射到高维空间,从而在高维空间中找到一个线性超平面来解决原始空间中的非线性问题。

第十三篇 机器学习(2)-朴素贝叶斯

朴素贝叶斯

朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理的分类算法,被广泛用于文本分类和其他分类问题。它被称为”朴素”是因为它假设每个特征与其他特征之间都是相互独立的,这是一个较为简化的假设,但在实践中,朴素贝叶斯通常表现得相当好。

在朴素贝叶斯中,我们考虑一个分类问题,其中 A 是类别,而 B 是特征。贝叶斯定理用于计算给定特征的情况下某个类别的概率。我们可以使用训练数据中的频率估计概率,并计算每个类别的概率。然后,给定一个新的特征向量,我们可以使用贝叶斯定理计算每个类别的后验概率,并选择具有最高概率的类别作为预测结果。

第十二篇 机器学习(1)-逻辑回归

逻辑回归

逻辑回归(Logistic Regression)是一种用于解决二分类问题的监督学习算法,尽管名称中包含”回归”一词,但实际上它用于分类任务。
逻辑回归使用一个假设函数(sigmoid函数),将输入特征的线性组合映射到一个在0和1之间的概率值。逻辑回归将概率值转换为二分类的决策,通常使用一个阈值(例如0.5)。逻辑回归使用交叉熵损失函数来衡量预测概率与实际标签之间的差异。损失函数的目标是最小化误差。

第十一篇 python(2)-flask+gunicorn+supervisor的python服务部署

过程

部署一个 Python 服务可以通过 Flask 框架、Gunicorn 服务器和 Supervisor 进程管理工具来完成。

1.安装 Flask、Gunicorn 和 Supervisor:

1
pip install flask gunicorn supervisor

  1. 创建一个 Python 脚本,例如 app.py,并添加一个简单的 Flask 应用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from flask import Flask

    app = Flask(__name__)

    @app.route('/')
    def hello():
    return "Hello, World!"

    if __name__ == '__main__':
    app.run()

3.创建 Gunicorn 配置文件:创建一个名为 gunicorn_config.py 的文件,配置 Gunicorn 服务器:

1
2
bind = '0.0.0.0:8000'
workers = 4

4.运行 Gunicorn 服务器:使用 Gunicorn 运行 Flask 应用:

1
gunicorn -c gunicorn_config.py app:app

5.创建 Supervisor 配置文件:创建一个名为 flask_app.conf 的配置文件,配置 Supervisor:

1
2
3
4
5
6
7
[program:flask_app]
directory=/path/to/your/app
command=/path/to/gunicorn -c /path/to/gunicorn_config.py app:app
autostart=true
autorestart=true
stderr_logfile=/var/log/flask_app.err.log
stdout_logfile=/var/log/flask_app.out.log

6.启动 Supervisor:启动 Supervisor 并加载配置文件:

1
sudo supervisord -c /etc/supervisor/supervisord.conf

7.检查应用程序状态:使用 Supervisorctl 命令检查应用程序的状态:

1
sudo supervisorctl status

第九篇 python(1)-语法进阶

yield

yield可以暂停一个函数的运行,返回值给函数调用者,并使得函数可以从上次离开的地方接着运行。通常我们可以借助yield来实现一个生成器。

生成器

生成器是一个可以产生一个序列的函数,调用生成器函数会产生一个生成器对象,并不会开始启动函数,只有当执行__next__()时函数才会执行。生成器时一个一次性操作,和我们常见的列表、字典等可以迭代的对象不同,列表等是可以无限次迭代的。

装饰器

python中函数是一等对象,所以函数可以像普通变量一样当作参数传给另一个函数的,装饰器可以在不改变另一个函数的情况下用来封装另一个函数以拓展这个被封装函数的功能,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。

装饰器不仅可以是函数,也可以是类。使用类装饰器主要依靠类的__call__方法。我们可以直接定义一个装饰器函数或者装饰器类,但是有个缺点是原函数的元信息不见了,比如函数的docstring__name__都会发生改变,此时我们可以使用functools.wrapswraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的函数中。