通用流程

 
模型设计:从数据中找规律

训练
- 损失函数:衡量模型输出与标签的差异 
- 优化器:梯度下降
- 并非所有的模型都需要损失函数 

套用模型:求解映射规律/对应法则

 
分类算法:预测输出都是离散量
回归算法:输出/预测的是连续量
聚类算法:没有标签的分类 

训练:数据 + 模型 -- 映射规则 

预测

 
套用学习来的规则,做预测/推理
    
模型评估

基准

 
先训练一个baseline模型,基线模型,基准定位 

后面的每次训练,优化,与基线相比,进步多少  

所以,模型第一步就是快速跑通整个流程,搭建一个baseline模型 

 
人工智能项目不可控因素比较多,
不像传统的电商,APP开发等项目,有固定的流程,
人工智能项目存在很多的风险,
大多在前期无法准备评估项目是否能搞定,只有试了才知道 

签合同之前,必须快速出一个baseline,
大概知道这个项目精度能达到一个什么样的程度

然后再去找更好的模型,筛选出更好的数据,然后替换上一版

优化,提升,这些工作存在的前提就是一个相对指标
    

 
有了基准之后,后续就是在 数据和模型 两个方面不断提升

这里模型泛指一切可以提升精度的方法
- 包含但不限于已有封装好的各种模型算法
- 还包括那些根据特定的业务场景开发出来的处理方法与技巧 
  

mean square error:通常用于 求/衡量/评估/度量 回归问题中两个分布的差异

 
数据以矩阵的形式进行计算,矩阵实则为向量组,样本集合

MSE实际是求模型输出向量与标签向量平方差的平均
这个平均是全体样本层面的平均
不可避免的会出现一些样本偏差比较大... 因为是平均
    
 
import numpy as np
y = np.array([[1,2,3]])
y_pred = np.array([[1,2,3]])

print(y**2)  # [[1 4 9]]

print(((y-y_pred)**2).mean())  #0.0

 
求两个分布对应序列位置上元素的差异:
各个位置上的元素作差,求平方,再取均值 

相似的公式,比如,求二维平面坐标系中两点的距离,
是各个维度上的元素作差,求平方,相加,再开方 

可以说mse借鉴了求两个事物之间距离的方法,
或者说mse本身与距离近似成正比  
    

ase

 
ase与mse相同的地方:
- 结果为一个数,单个数值
- 正数,
   - 虽然这不是必备条件
   - 因为负数也能反映两个分布的差异,
   - 但还是有很多函数设计为将结果转化为正数

差异
- ase的计算比mse简单的多,数据量越大差异越大
- ase不方便求导,还绝对值,拐点处两侧导数不一样
- mse曲线任何一段都是平滑的,方便求导
- ase用的少,回归问题多选择mse 
    

 
# 模型评估
import numpy as np 
np.abs(y_pred - y_test)

这里说的规律,指统计规律,指那些明显能感到有规律,不是随机的现象

 
比如,人脸识别,语言识别,自动驾驶...
不管在图像还是序列上,这些现象都存在明显的规律 
虽然不知道生命怎么具备这能力的,但100%可以确定,是有规律的... 

比如,一车沙子倾倒于地,
形成的沙堆的形状基本就是一个中间高,周边低的沙堆
这样的现象就叫有统计规律,可以使用模型预测 

如果只扔两颗沙子,那掉落的位置可真就随机了,
数据量达到一定程度才能体现出其统计规律


股票可以预测,因为它高高低低差不多,受影响的因素通过业务专业分析后会更加固定

彩票就不一样,它或者有其规律,但受影响的因素太多,并且尚无彩票业务专家,
就算有,人家也不会来给你共享一买就中就赚钱的方法,
另外,彩票的数据太少了,
比扔两颗沙子就推断出如果扔一车沙子必定呈现中间高两边低的统计规律还要难
简单说,可以认为彩票是随机的

但本人的确还有一些其他想法,本人尚无时间验证,能读到这里尚且对此感兴趣的,可以试试:
任何随机事物的不确定性,都可以通过对事件进一步细分,使之确定性增加 
- 首先,定下一个baseline
    - 比如,你不用模型,买100,平均中10块,这就是一个基线
    - 用了模型,买100,中20,这是模型的基线 
        - 你从五个维度考虑,就把这五个维度记下来

- 其次,增加维度,增加其他辅助评估算法
    - 本人做过欺诈模型,先生成7000多个变量,再选出其中100有用的
    - 就这,也增加不了多少概率,还要从业务再划分出50个维度来评价这个模型得分
    - 所以,要想达到买100中80的程度,可能需要好几千,甚至上万个维度的变量
    - 还要外加数百个辅助维度才有可能
    - 个人评估啊,就算能有结果,所耗费的精力用于一个行业的话,稳稳的专家了... 
- 最后,善意的提醒一下,
    - 如果不是走头无路,还是搞点别的吧,
    - 别预测彩票以及所有像彩票这样无规律的现象了,
    - 有人付费让你研究或者自己不差钱就想干点能让人意外的除外...
        - 科研的前期大多就是这样发展起来的...
        - 现代科学是全人类数千年尝试的结果...
        - 有 太多·太多·太多 
        的人终其一生,都在研究试错且无一成果!

    

 
发生的事情有其确定性,未发生的事情,由 规律(因果)+概率 组合
- 未发生事情的概率,即不确定性,是因为我们掌握的信息不足才不确定的?
- 还是,这个宇宙真的就有一条规律,是那遁去的一,永远不可捉摸?
- 这个本人真是不知道,想了很多次,虽然书上的道理写的很清楚,很明白,
- 但自己还是骗不自己,就是不知道!
    

评估方向

 
效果很差,是不是只搞模型就行?不是的
很大的可能是数据没有这种规律,或者规律体现的不够线性
- 找专家,增加维度,增加信息量,增加变量
- 让规律变得更加明显,更加线性化 
- 就像捉迷藏游戏一样,
    - 这个游戏正直的核心不是你藏到一个别人很难找的地方,
    - 真的让人找不到,如此,这游戏就没法玩了 

 
数据特点,规模,量级

模型复杂度,计算量,计算代价,性能,效率,准确率

    

工作常态:效果很差怎么办?

 
大部分情况是这样的
- 天天研究数据和模型,但效果却很难让人满意,
- 研究了几个月,发现 性能/效果 没有一点点的提高... 
- 这是很常见的事,
- 不然呢,毕竟不是谁遇到问题都能很快解决的... 
- 回顾过去近百年,整个行业/圈子也就10~20年才出1~3个突破性的论文

PSI小于0.1时候模型稳定性很高,0.1-0.2一般

 
模型稳定度指标(population stability index ,PSI)可衡量测试样本及模型开发样本评分的的分布差异,为最常见的模型稳定度评估指针。其实PSI表示的就是按分数分档后,针对不同样本,或者不同时间的样本,population分布是否有变化,就是看各个分数区间内人数占总人数的占比是否有显著变化

PSI小于0.1时候模型稳定性很高,0.1-0.2一般,需要进一步研究,大于0.2模型稳定性差,建议修复。

psi计算公式为:psi = sum((实际占比-预期占比)* ln(实际占比/预期占比))

 
测试集假设有1000条,分m组(比如m=10),不一定是等分,等分也没关系,

每一组计算:
(模型预测数/1000 - 实际标签数/1000)×ln(模型预测数/实际标签数)

PSI=这m组计算之和 
    
模型保存

 
`joblib` 是 Python 中用于**高效保存和加载 Python 对象**(尤其是包含 NumPy 数组的大型对象)的库,常用于机器学习模型的持久化。它比 `pickle` 更适合处理数值数据,速度快、效率高。

在机器学习中,我们常用 `joblib.dump()` 保存训练好的模型,用 `joblib.load()` 加载模型进行预测。

---

## ✅ 1. 基本用法

### 📦 保存对象:`joblib.dump()`

```python
from joblib import dump, load

# 假设 model 是你训练好的模型(如 XGBoost、CatBoost、Sklearn 模型等)
dump(model, 'model.joblib')
```

- `'model.joblib'`:保存的文件名(推荐 `.joblib` 或 `.pkl` 扩展名)
- 也可以保存多个对象:
    ```python
    dump([model, scaler, label_encoder], 'pipeline.joblib')
    ```

---

### 📂 加载对象:`joblib.load()`

```python
from joblib import load

# 加载之前保存的模型
model = load('model.joblib')

# 如果保存的是多个对象
# model, scaler, label_encoder = load('pipeline.joblib')
```

加载后,`model` 就可以像训练时一样使用,例如:

```python
y_pred = model.predict(X_test)
```

---

## ✅ 2. 完整示例(以 XGBoost 为例)

```python
import xgboost as xgb
from joblib import dump, load
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# 生成数据
X, y = make_classification(n_samples=1000, n_features=10, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练模型
model = xgb.XGBClassifier(n_estimators=100, max_depth=3)
model.fit(X_train, y_train)

# 保存模型
dump(model, 'xgb_model.joblib')
print("模型已保存")

# 加载模型
loaded_model = load('xgb_model.joblib')
print("模型已加载")

# 使用加载的模型预测
y_pred = loaded_model.predict(X_test)
print("预测完成,前10个预测结果:", y_pred[:10])
```

---

## ✅ 3. 高级用法

### 🔧 压缩保存(减小文件大小)

```python
# 使用压缩,0=无压缩,9=最大压缩
dump(model, 'model.joblib', compress=3)
```

> 推荐 `compress=3`,在压缩速度和体积之间取得良好平衡。

### 📥 加载压缩文件(无需额外操作)

```python
model = load('model.joblib')  # 自动解压,无需指定
```

---

### 🗂️ 保存到文件对象(如 BytesIO)

```python
from io import BytesIO

buffer = BytesIO()
dump(model, buffer)  # 保存到内存
buffer.seek(0)

# 稍后加载
model = load(buffer)
```

---

## ✅ 4. 与 `pickle` 的对比

| 特性 | `joblib` | `pickle` |
|------|----------|----------|
| 数值数据效率 | ⚡ 高(尤其 NumPy 数组) | 一般 |
| 语法 | `dump(obj, filename)` | `pickle.dump(obj, file)` |
| 适合场景 | 机器学习模型、NumPy 数组 | 通用 Python 对象 |
| 压缩支持 | ✅ 内置 `compress` 参数 | 需配合 `gzip` 等 |

> ✅ **结论:机器学习项目中优先使用 `joblib`**

---

## ✅ 5. 注意事项

1. **兼容性**:用 `joblib` 保存的模型,最好也用相同或兼容版本的库加载。
2. **安全性**:不要加载来源不明的 `.joblib` 文件,可能执行恶意代码(反序列化风险)。
3. **文件路径**:确保保存路径有写权限,加载时路径正确。
4. **模型依赖**:确保加载环境安装了模型所需的库(如 `xgboost`, `sklearn`, `catboost` 等)。

---

## ✅ 总结

| 操作 | 代码 |
|------|------|
| 保存模型 | `dump(model, 'model.joblib')` |
| 保存并压缩 | `dump(model, 'model.joblib', compress=3)` |
| 加载模型 | `model = load('model.joblib')` |

📌 **推荐在机器学习项目中使用 `joblib` 来保存和加载模型**,简单、高效、可靠。

    

 

    

 

    

 
`pickle` 是 Python 内置的标准库,用于**序列化(Serialization)和反序列化(Deserialization)Python 对象**。你可以用它将几乎任何 Python 对象保存到文件中,之后再从文件中恢复原对象,这一过程也称为“对象持久化”。

在机器学习、数据处理等场景中,常用于保存模型、数据、配置等。

---

## ✅ 1. 核心函数

- `pickle.dump(obj, file)`:将对象 `obj` 序列化并写入文件。
- `pickle.load(file)`:从文件中读取并反序列化为 Python 对象。

---

## ✅ 2. 基本用法示例

### 📦 1. 使用 `pickle.dump()` 保存对象

```python
import pickle

# 要保存的 Python 对象(可以是列表、字典、模型等)
data = {
    'name': 'Alice',
    'age': 30,
    'scores': [85, 92, 78],
    'is_student': False
}

# 打开文件(二进制写模式 'wb')
with open('data.pkl', 'wb') as f:
    pickle.dump(data, f)

print("对象已保存到 data.pkl")
```

> ⚠️ 注意:必须使用 `'wb'` 模式(write binary),因为 `pickle` 存储的是字节数据。

---

### 📂 2. 使用 `pickle.load()` 加载对象

```python
import pickle

# 打开文件(二进制读模式 'rb')
with open('data.pkl', 'rb') as f:
    loaded_data = pickle.load(f)

print("加载的对象:", loaded_data)
# 输出: {'name': 'Alice', 'age': 30, 'scores': [85, 92, 78], 'is_student': False}
```

> ⚠️ 注意:必须使用 `'rb'` 模式(read binary)。

---

## ✅ 3. 保存和加载机器学习模型(以 sklearn 为例)

```python
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
import pickle

# 生成数据
X, y = make_classification(n_samples=1000, n_features=4, n_classes=2, random_state=42)

# 训练模型
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)

# 保存模型
with open('model.pkl', 'wb') as f:
    pickle.dump(model, f)

print("模型已保存")

# 加载模型
with open('model.pkl', 'rb') as f:
    loaded_model = pickle.load(f)

# 使用加载的模型预测
print("预测结果:", loaded_model.predict([[0.1, 0.2, 0.3, 0.4]]))
```

---

## ✅ 4. 高级用法

### 🔧 1. 一次性保存/加载多个对象

```python
# 保存多个对象
obj1 = [1, 2, 3]
obj2 = {'a': 1, 'b': 2}
with open('multi.pkl', 'wb') as f:
    pickle.dump(obj1, f)
    pickle.dump(obj2, f)

# 加载时按顺序读取
with open('multi.pkl', 'rb') as f:
    a = pickle.load(f)  # 第一个对象
    b = pickle.load(f)  # 第二个对象
print(a, b)  # [1, 2, 3] {'a': 1, 'b': 2}
```

### 🧊 2. 控制序列化协议(可选)

```python
# 使用更高版本的协议(性能更好,但兼容性略差)
pickle.dump(data, f, protocol=4)  # protocol=5 在 Python 3.8+ 中支持大文件优化
```

> 常见协议版本:`0`, `1`, `2`, `3`, `4`, `5`。推荐使用 `protocol=4` 或 `5` 提升性能。

---

## ✅ 5. `pickle` vs `joblib`

| 特性 | `pickle` | `joblib` |
|------|----------|----------|
| 是否内置 | ✅ 是 | ❌ 需 `pip install joblib` |
| 数值数据效率 | 一般 | ⚡ 高(尤其 NumPy 数组、模型) |
| 语法 | `pickle.dump(obj, file)` | `joblib.dump(obj, filename)` |
| 文件操作 | 需手动打开文件 | 可直接传文件名 |
| 压缩支持 | 需配合 `gzip` | 内置 `compress` 参数 |
| 推荐场景 | 通用对象序列化 | 机器学习模型、数组 |

> ✅ **建议**:
> - 机器学习模型、NumPy 数组 → 优先用 `joblib`
> - 通用 Python 对象、简单脚本 → 可用 `pickle`

---

## ✅ 6. 安全注意事项 ⚠️

- **不要加载来源不明的 `.pkl` 文件**!
- `pickle` 在反序列化时可能执行任意代码,存在**安全风险**。
- 例如:恶意构造的 `.pkl` 文件可在你 `pickle.load()` 时执行系统命令。

> 🔐 生产环境务必确保 `.pkl` 文件来源可信。

---

## ✅ 总结

| 操作 | 代码 |
|------|------|
| 保存对象 | `pickle.dump(obj, open('file.pkl', 'wb'))` |
| 加载对象 | `obj = pickle.load(open('file.pkl', 'rb'))` |
| 推荐用途 | 通用对象序列化 |
| 注意事项 | 二进制模式、安全风险、协议版本 |

📌 `pickle` 是 Python 对象持久化的通用工具,简单强大,但需注意安全性和性能选择。

    

 

    

 

    

 


 

  

 


参考