├── .DS_Store ├── Computer_composition └── 冯·诺伊曼体系结构.md ├── Data_structure ├── 《图解算法》学习笔记.md ├── 复杂度分析.md └── 数据结构_数组(Array).md ├── Database ├── MacOS 安装 MySQL.md ├── MySQL 事务原理理解.md ├── MySQL 基础架构.md ├── MySQL 日志系统.md ├── Pyhton ORM 框架操作 MySQL.md ├── Python 中使用 MySQL.md ├── SQL 关系数据库概述.md ├── SQL 创建数据库表.md └── SQL 查询数据.md ├── Machine_Learning ├── Attention 机制理解(1) --- Seq2Seq 中的 attention.md ├── CNN简述.md ├── KNN简单实现.md ├── Keras 中 Callbacks.md ├── Keras 储存和载入训练好的模型.md ├── LSTM 新手常见问题.md ├── RNN概述.md ├── SVM 原理详述.md ├── SVM 用作(多项)回归原理 +sklearn实现代码.md ├── SVM原理简述.md ├── Tenserflow 基础知识.md ├── TensorFlow Probability 中的结构化时间序列模型.md ├── keras 模型结构可视化.md ├── keras中模型的保存和重新导入.md ├── 使用 LSTM 预测时间序列数据时候的陷阱.md ├── 加速 python 数据分析的小技巧.md ├── 单元线性回归.md ├── 多元线性回归.md ├── 提取 keras 中的模型 weights.md ├── 数据处理 5 种采样方法.md ├── 时间序列数据分析步骤.md ├── 时间序列预测中的 Baseline predictions.md ├── 机器学习中的特征选择.md ├── 机器学习中的随机性.md ├── 机器学习中自动化特征工程(Python).md ├── 机器学习中训练集和测试集验证集.md ├── 机器学习数据预处理.md ├── 深度学习进行信号处理和时间序列分析.md ├── 理解为什么 RNN 模型这么有效.md ├── 神经网络(RNN) 参数调节.md ├── 神经网络模型简述.md ├── 粒子群算法.md └── 罗辑回归.md ├── Network_protocol ├── .DS_Store ├── 网络协议- CDN 分发系统.md ├── 网络协议-DNS协议.md ├── 网络协议-HTTPS协议.md ├── 网络协议-HTTP协议.md ├── 网络协议-ICMP.md ├── 网络协议-P2P协议.md ├── 网络协议-TCP.md ├── 网络协议-TCP和UDP.md ├── 网络协议-ip地址.md ├── 网络协议-交换机和STP.md ├── 网络协议-数据中心.md ├── 网络协议-流媒体协议.md ├── 网络协议-物理层和MAC层.md ├── 网络协议-网关.md ├── 网络协议-路由协议.md └── 网络协议-配置IP地址.md ├── Python ├── 写代码时如何创建有意义的名称.md ├── .DS_Store ├── Matplotlib 科学绘图常用命令总结.md ├── Pyhton ORM 框架操作 MySQL.md ├── Python Pandas 使用更高效.md ├── Python 函数中的 -> 是什么意思.md ├── Python3.8 有用的新特性.md ├── python 垃圾回收机制.md ├── python 调试和测试.md ├── python 中 Print()函数详解.md ├── python 中 f Strings用法.md ├── python 中匿名函数 lambda.md ├── python 中字典和集合.md ├── python 中字符串.md ├── python 中常用迭代方法.md ├── python 中异常处理.md ├── python 中条件和循环.md ├── python 中自定义函数.md ├── python 中输入和输出.md ├── python 列表和元组.md ├── python 协程.md ├── python 参数传递.md ├── python 并发编程 Futures.md ├── python 模块化.md ├── python 装饰器.md ├── python 迭代器和生成器.md ├── python小技巧 : 函数参数解包(*, **).md ├── python小技巧 : 字典按照 value 排序.md ├── python小技巧 :namedtuples 简洁定义class.md ├── python小技巧 :字典中的 get() 方法.md ├── python小技巧 :快速合并两个字典.md ├── 全局解释器锁(GIL).md └── 面向对象编程.md ├── README.md ├── Recommendation_Agorithm ├── .DS_Store ├── Image │ ├── AutoEncoder.png │ ├── README.md │ ├── RNN--Using.png │ ├── SVD++.png │ ├── Word2vec 预测.png │ ├── YouTube-神经网络.png │ ├── 偏置信息的SVD、.png │ ├── 内容推荐总结.jpg │ ├── 内容推荐的框架图.png │ ├── 卡方检验.png │ ├── 开源-内容分析、.png │ ├── 开源-协同过滤+矩阵分解.png │ ├── 开源-混合模型.png │ ├── 开源项目-推荐系统.png │ ├── 循环神经网络.png │ ├── 损失函数定义.png │ ├── 推荐系统_概念篇.jpg │ ├── 推荐计算公式.png │ ├── 深度学习总结.jpg │ ├── 皮尔逊相关.png │ ├── 矩阵--神经网络.png │ ├── 矩阵分解总结.jpg │ ├── 置信度+.png │ └── 近邻推荐总结.jpg ├── Papers_Learning │ └── README.md ├── README.md ├── Recsys2018_Summary │ ├── .DS_Store │ ├── Image │ │ ├── re_1.png │ │ ├── re_apploication.png │ │ ├── re_dataset.png │ │ ├── re_techs.png │ │ ├── re_可解释性1.png │ │ ├── re_新问题.png │ │ ├── re_新问题2.png │ │ └── re_新问题3.png │ └── README.md ├── 内容推荐.md ├── 排行榜.md ├── 推荐系统_概念.md ├── 深度学习--推荐系统.md ├── 矩阵分解.md └── 近邻推荐-协同过滤.md └── Techs ├── Chrome实用插件.md ├── Git 命令学习.md ├── GitHub使用技巧.md ├── Jupyter Notebook 使用技巧.md ├── Mac app 使用推荐.md └── mac iterm2 配置.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/.DS_Store -------------------------------------------------------------------------------- /Computer_composition/冯·诺伊曼体系结构.md: -------------------------------------------------------------------------------- 1 | * 本文为极客时间 徐文浩老师的《深入浅出计算机组成原理课程》专栏课程笔记。 2 | 3 | [原文link](https://time.geekbang.org/column/article/91793) 4 | 5 | --- 6 | 7 | 8 | ## 1. 计算机基本硬件组成 9 | 10 | 1. CPU 中央处理器 : 所有的计算都是由 CPU 进行的。 11 | 12 | 2. 内存 : 存放在内存的数据和程序被 CPU读取,CPU计算完成之后将数据写回到内存之中。 13 | 14 | 3. 主板 : 上述的 CPU和 内存都是要插在主板上 15 | 16 | 主板的芯片组控制数据传输的流转(从哪里到哪里);主板的总线是数据传输的“高速公路”,总线速度决定了数据传输的速度 17 | 18 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/6nhl2.jpg) 19 | 20 | 4. I/O 设备: 输入输出设备: 鼠标 键盘 显示器 21 | 22 | 5. 硬盘 永久储存数据 23 | > 不是必须的,可以通过局域网读写远程网络硬盘数据 24 | 25 | 6. 显卡(Graphics Card): 目前计算机主板都有内置的显卡,但是需求如果更大(游戏,深度学习)就需要单独的显卡插在主板上。 26 | 27 | 鼠标键盘硬盘 等IO 设备,通过主板上的**南桥**芯片组来和 CPU之间通信。 28 | > 之所以叫南桥: 一个是因为通常放在主板的南面,作用就是 桥梁 29 | 30 | 内存 显卡和 CPU 之间的通讯 通过主板的**北桥** 31 | > 目前北桥芯片组 已经移到 CPU内部 32 | 33 | ---- 34 | 35 | ## 2. 智能手机的组成 36 | 37 | 1. CPU 内存 网络通信,摄像头都疯撞到一个芯片,然后再嵌入到手机主板上面 38 | 39 | 2. 只有一个 SD 这个类似 硬盘功能的储存卡插槽 40 | 41 | 42 | 43 | --- 44 | 45 | ## 3. 冯· 诺伊曼体系结构 46 | 47 | **储存程序计算机** 48 | 49 | 50 | 1. 可编程 : 51 | 52 | 计算机是由各种门 电路组合而成的,组装成一个固定的电路板,来完成一个特定的计算程序。一旦需要修改狗功能,就需要重新组装电路。 53 | 例如 计算器 54 | 55 | 2. 储存: 程序储存在计算机的内存里买呢,加载不同的程序解决不同的问题 56 | 57 | 不可储存计算机: Plugborad 插线板式计算机: 编写好的程序不能储存下一次使用。 58 | 59 | ---- 60 | 61 | 冯· 诺伊曼体系 中计算机应该有的组成部分 : 62 | 63 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/89vfs.jpg) 64 | 65 | 66 | 1. 处理器单元(Processing Unit) -- 运算器 67 | 包含 算术逻辑单元(ALU) 和 处理器寄存器 68 | 完成各种算数和逻辑运算 69 | 70 | 2. 控制器单元(Control Unit CU): 71 | 包含 指令寄存器 和 程序计数器 72 | 73 | 控制程序的流程 74 | 75 | **运算器单元和控制器单元 组成了 CPU** 76 | 77 | 78 | 3. 内存: 储存数据和指令(Instruction) + 外部储存(硬盘) 79 | 80 | 4. 输入输出设备,以及相应的输入和输出机制 81 | 82 | ---- 83 | 84 | **计算机程序,也都可以抽象为从输入设备读取输入信息,通过运算器和控制器来执行储存在储存器里面的程序,最后把结果输出到输出设备中** 85 | 86 | 87 | ---- 88 | 89 | ## 4. 图灵机 90 | 91 | 冯· 诺伊曼机侧重硬件抽象,图灵机侧重计算抽象 92 | 93 | 图灵认为凡是可以通过算法解决的问题也一定可以用图灵机解决 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /Data_structure/复杂度分析.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文为极客时间 王争老师的《数据结构与算法之美》专栏课程笔记。整理内容,改用 python 实现,一点扩展内容。 3 | 4 | [原文link](https://time.geekbang.org/column/intro/126) 5 | 6 | 7 | ---- 8 | 9 | ## 1. 复杂度分析 原因 10 | 11 | 数据结构和算法的目的是-----代码运行的更快,更节省储存空间 12 | 13 | 需要一个 不依靠测试环境和测试数据规模的方法来粗略的估计算法的执行效率 14 | 15 | ----- 16 | 17 | ## 2. 复杂度表示法 : 大 O 18 | 19 | 对于 CPU ,程序中的每行代码都执行着类似的操作: 20 | 21 | 读数据 — 运算 — 写数据 22 | 23 | 每行代码执行的时间不一样,但是可以粗略的假设都一样: Unit_time 24 | 25 | ```python 26 | def cal(n): 27 | """ 28 | 计算1,2,3 的累加和 29 | """ 30 | sum = 0 31 | for i in range(n): 32 | sum= sum +i 33 | return sum 34 | 35 | ``` 36 | 37 | 对于上面的代码, for 循环中的两行都是运行了 n 次 38 | 39 | 总的执行时间是 T(n) = (2n+1)* unit_time 40 | 41 | T(n) 和代码的执行次数成正比 42 | 43 | ```python 44 | def cal_2(n): 45 | """ 46 | 计算 1+ (1+2+...n)+ 2 +(1+2+...n) + ....n + (1+...n) 47 | """ 48 | sum = 0 49 | for i in range(n): 50 | for j in range(n): 51 | sum = sum + i +j 52 | return sum 53 | 54 | 55 | ``` 56 | 57 | 同样对于上面的代码,假设每个语句的执行时间是 unit_time, 58 | 59 | 对于 for 循环,执行了 n* (2n) 个 Unit_time 60 | 61 | T(n) = 2n^2 + 1 62 | 63 | ---- 64 | 65 | 使用 大 O表示法: 66 | 67 | T(n) = O(2n+1) 68 | 69 | T(n) = O(2n^2 + 1) 70 | 71 | **其中 大O 时间复杂度表示的不是代码具体的执行时间,而是代码执行时间随着数据规模增长的变化趋势— 渐进时间复杂度** 72 | 73 | 当 n 很大的时候,我们可以只关注高阶项,忽略低阶和系数---因为这些不会影响主要的增长趋势。 74 | 75 | T(n) = O(n) 76 | 77 | T(n) = O(n^2 ) 78 | 79 | ----- 80 | 81 | ## 3. 时间复杂度分析方法 82 | 83 | 1. 关注循环执行次数多的部分代码 84 | 2. 总的时间复杂度等于量级最大的代码部分的时间复杂度 85 | 3. 嵌套的代码的复杂度等于内外复杂度乘积 86 | 87 | ## 4. 常见的时间复杂度 88 | 89 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/70dk3.jpg) 90 | 91 | 1. O(1): 92 | 93 | ```python 94 | i = 1 95 | j = 2 96 | sum = i+j 97 | ``` 98 | 99 | 算法中不存在循环语句,递归语句,时间复杂度都是 100 | 101 | 2. O(logn),O(nlogn) 102 | 103 | ```python 104 | i = 1 105 | while(i 通过换底公式,不同 底之间差一个常数系 115 | 116 | 3. O(m+n),O(m * n) 117 | 118 | 代码的复杂度是由 两个数据规模决定的— 和上面的规则不矛盾,因为不知道哪一个大 119 | 120 | ```python 121 | def cal_3(m,n): 122 | sum_1 = 0 123 | sum_2 = 0 124 | for i in range(m): 125 | sum_1 = sum_1 + i 126 | for j in range(n): 127 | sum_2 = sum_2 + j 128 | return sum_1 + sum_2 129 | ``` 130 | 131 | ----- 132 | 133 | ## 5. 最好 最坏情况时间复杂度 134 | 135 | ```python 136 | def find(list0,x): 137 | """ 138 | 寻找列表中的变量的位置 139 | 如果没有找到,就返回 -1 140 | """ 141 | i = 0 142 | pos = -1 143 | while i < len(list): 144 | if list0[i] == x: 145 | pos = i 146 | break # 找到之后 跳出循环 147 | i = i+1 148 | return pos 149 | ``` 150 | 151 | 分析上面代码的时间复杂度: 152 | 153 | 1. 如果第一个就是要找的 x, 时间复杂度就是O(1), 154 | 2. 如果列表中不包含x, 那么时间复杂度就是 O(n) 155 | 156 | **最好时间复杂度:** 最理想的情况下,执行代码的时间复杂度。 — 1 157 | 158 | **最坏时间复杂度:** 最糟糕的情况下,执行代码的时间复杂度。 —2 159 | 160 | ---- 161 | 162 | ## 6. 平均情况时间复杂度 163 | 164 | 计算所有情况的期望值 165 | 166 | 分析上面的代码:假定要查找的x 在数组和不在数组的概率 各 0.5,如果在,出现在 n 个位置的概率相同, 1/n,所以得到下面的 167 | 168 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0xxq2.jpg) 169 | 170 | 之后使用 O 表示,平均时间复杂度是 O(n) 171 | 172 | ------ 173 | 174 | ## 7. 均摊时间复杂度 175 | 176 | ```python 177 | list_0 = [0 for i in range(10)] # 初始化一个定长的列表 178 | count = 0 179 | def insert_val(val): 180 | """ 181 | 向列表中插入数据,如果有位置就直接插入 182 | 如果数组满了,就将数组求和,求和结果放在第一个位置 183 | 然后插入新的数据 184 | """ 185 | if count == len(list_0): 186 | sum = 0 187 | i = 0 188 | while i < len(list_0): 189 | sum = sum + list_0[i] 190 | i = i +1 191 | list_0[0] = sum 192 | count = 1 193 | list_0[count] = val 194 | count = count + 1 195 | 196 | 197 | ``` 198 | 199 | 分析上面的代码: 对于insert_val() 函数来说,出现O(1) 和 O(n) 的pinky是有规律的,一般是 一个O(n) 之后 紧跟n-1 个O(1),将耗时较多的O(n) 那次的操作,直接均摊到 n-1 个耗时少的 O(1) 200 | 201 | > 大部分时间复杂度底,个别情况时间复杂度较高,存在时序关系。或者说 出现 O(1) 的次数远大于 O(n) 的次数 202 | 203 | ---- 204 | 205 | 206 | 207 | ## 8. 空间复杂度分析 208 | 209 | 代码申请 空间的大小 210 | 211 | -------------------------------------------------------------------------------- /Data_structure/数据结构_数组(Array).md: -------------------------------------------------------------------------------- 1 | * 本文为极客时间 王争老师的《数据结构与算法之美》专栏课程笔记。整理内容,改用 python 实现,一点扩展内容。 2 | 3 | [原文link](https://time.geekbang.org/column/intro/126) 4 | 5 | --- 6 | 7 | 8 | ## 1. 数组(Array)— Define: 9 | 10 | 数组是一种**线性表**数据结构。它利用一组**连续的内存空间**,储存一组具有**相同类型的数据**。 11 | 12 | 1. 线性表 13 | 14 | 数组, 队列,链表,栈 等 15 | 16 | 数据排列成一条线,只能向前和向后。 17 | 18 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/f8m3h.png) 19 | 20 | 2. 非线性表: 21 | 22 | 二叉树,图等,数据之间不是简单的前后关系。 23 | 24 | 3. 连续的内存空间 25 | 26 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/tsklt.png) 27 | 28 | 计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。 29 | 随机访问数组中的元素的时候,首先激素那 元素的内存地址 30 | 31 | ```python 32 | a[i]_address = base_address + i * data_type_size 33 | 34 | # 对于二位数组 m*n 35 | 36 | a[i][j]_address = base_address + ( i * n + j) * type_size 37 | 38 | 39 | ``` 40 | 如上图所示 base_address = 1000, data_type_size 是数组中每个元素的大小,数组储存 int , 4个字节 41 | 42 | > 数组根据下标随机访问的时间复杂度是 O(1), 正常查找的时间复杂度是 O(logn) 43 | 44 | 45 | ## 2. 插入和删除 46 | 47 | ### 插入操作 48 | 49 | 50 | 1. 时间复杂度 --- 数组有序 51 | 对于有序数组,插入一个数据在 k 位置, k 之后的数据都要向后移动一个位置 52 | * 如果是在末尾, 时间复杂度 O(1) 53 | * 如果是在开头、 时间复杂度是 O(n) 54 | * 计算平均时间复杂度 (1+2+3...+n)/n = O(n) 55 | 56 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/grn7y.png) 57 | 58 | 2. 时间复杂度 --- 数组无序 59 | 对于无序数组,直接将 k 位置的数据搬移到数组元素的最后,把新的元素插入第 k 个位置 60 | * 时间复杂度 是 O(1) 61 | 62 | ### 删除操作 63 | 64 | 1. 常规删除 65 | 类似于插入操作,进行数据删除的时候,为了保持内训的连续性,需要进行数据搬移 66 | * 如果是在末尾, 时间复杂度 O(1) 67 | * 如果是在开头、 时间复杂度是 O(n) 68 | * 计算平均时间复杂度 (1+2+3...+n)/n = O(n) 69 | 70 | 2. 多次删除操作一起执行 71 | 72 | 每次的删除操作不是真的去搬移数据,而是记录数据已经被删除了,当数组没有更多空间储存数据的时候,再触发执行一次删除操作。 73 | 74 | ## 3. 为什么 数据编号从 0 开始 75 | 76 | 根据内存公式来说,下标的定义应该是偏移 a[0] 就是偏移为0 的位置,就是首地址 77 | 78 | 如果数组从1 开始计数 79 | 80 | ```python 81 | a[k]_address = base_address + (k-1)*type_size 82 | 83 | ``` 84 | 85 | 每次访问数组,都多了一次减法运算,多了一个减法指令, 86 | 为了效率的最优化,从 0 开始编号 87 | 88 | ------ 89 | ## 4. 代码实现数组 90 | 91 | 1. 数组可以随意访问元素 92 | 2. 数组支持 插入删除操作 93 | 94 | ```python 95 | 96 | class Array_define(object): 97 | """docstring for Array_define""" 98 | def __init__(self, capcity: int): 99 | """ 100 | 初始化一个 大小固定的空数组 101 | 102 | """ 103 | self._data = [] 104 | self._capcity = capcity 105 | 106 | def __getitem__(self,positon: int): 107 | """ 108 | 使用 订制类实现访问数据中任意一项 109 | """ 110 | if not isinstance(positon,int): 111 | raise ValueError('input must be an integer !') 112 | return self._data[positon] 113 | 114 | def __setitem__(self,index : int,value): 115 | """ 116 | 使用 订制类实现外部 修改属性 117 | """ 118 | if not isinstance(index,int): 119 | raise ValueError('index must be an integer !') 120 | self._data[index] = value 121 | 122 | def __len__(self): 123 | """ 124 | 使用 订制类 获取列表的长度 125 | """ 126 | return len(self._data) 127 | 128 | def __iter__(self): 129 | """ 130 | 使用 订制类 数组可以进行 for 循环操作 131 | """ 132 | for item in self._data: 133 | yield item 134 | 135 | def find(self,index: int): 136 | return self._data[index] 137 | 138 | def delete(self,index:int): 139 | try: 140 | self._data.pop(index) 141 | return True 142 | except IndexError: 143 | return False 144 | 145 | def insert(self, index: int,value): 146 | if len(self) >= self._capcity: 147 | return False 148 | else: 149 | self._data.insert(index,value) 150 | 151 | def print_all(self): 152 | for item in self: 153 | print(item) 154 | 155 | def test(): 156 | arr = Array_define(5) 157 | arr.insert(0, 3) 158 | arr.insert(0, 4) 159 | arr.insert(1, 5) 160 | arr.insert(3, 9) 161 | arr.insert(3, 10) 162 | assert arr.insert(0, 100) is False # 超过数组的大小 163 | assert len(arr) == 5 164 | assert arr.find(1) == 5 165 | assert arr.delete(4) is True 166 | arr.print_all() 167 | if __name__ == "main": 168 | test() 169 | ``` 170 | 171 | 测试结果: 172 | 173 | 174 | ```python 175 | test() 176 | 4 177 | 5 178 | 3 179 | 10 180 | 181 | ``` 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /Database/MacOS 安装 MySQL.md: -------------------------------------------------------------------------------- 1 | ## 1. 进入官网下载 最新社区版 2 | 3 | https://dev.mysql.com/downloads/mysql/ 4 | 5 | 6 | ![](https://i.loli.net/2019/07/13/5d2951d921b9b71957.png) 7 | 8 | 我选择的是 dmg 安装包 9 | 10 | 11 | ## 2. 安装指引安装,**中间会设置 root 的密码,记住,以后登陆要用** 12 | 13 | 14 | ## 3. 终端连接 SQL 15 | 16 | * 在终端添加 MySQL 的路径 17 | 18 | ``` 19 | PATH="$PATH":/usr/local/mysql/bin 20 | ``` 21 | 22 | 之后通过下面的命令登陆 23 | 24 | ```sql 25 | 26 | mysql -u root -p 27 | 28 | ``` 29 | 30 | * -u 后面接的是用户名 ,默认是 root 31 | * -p 后面接的是密码, 32 | 33 | * 省略了 -h, 登陆当前主机的 MySQL 数据库可以省略,登陆远程主机的 需要加入远程主机的 IP地址 34 | 35 | 36 | ``` 37 | 38 | mysql -h 202.116.96.96 -u root -p 39 | ``` 40 | 41 | ![](https://i.loli.net/2019/07/13/5d295344149c596808.png) 42 | 43 | 44 | ## 4. 检查 MySQL 编码 45 | 46 | ```sql 47 | show variables like '%char%'; 48 | 49 | ``` 50 | ![](https://i.loli.net/2019/07/13/5d29557f6964d82823.png) 51 | 52 | 编码 utf8mb4 和 utf8 完全兼容,支持最新的 Unicode 标准, 可以显示 emoji 53 | 54 | 55 | 56 | 57 | ---- 58 | 59 | 60 | # 4. 参考 61 | 62 | https://www.jianshu.com/p/07a9826898c0 63 | 64 | https://www.liaoxuefeng.com/wiki/1177760294764384/1179611020917408 -------------------------------------------------------------------------------- /Database/MySQL 基础架构.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 丁奇老师 的《 MySQL 实战45讲》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. MySQL 基础架构 6 | 7 | 8 | ![](https://i.loli.net/2019/07/15/5d2c80370199a68830.png) 9 | 10 | * MySQL 分为 Serve层 和 储存引擎层 11 | 12 | 1. Serve 层: 13 | 14 | 包括 MySQL 大多数核心功能,以及所有的内置函数 15 | 16 | 17 | 2. 储存引擎层: 18 | 19 | 负责数据的储存和提取, 默认储存引擎是 InnoDB 20 | 21 | 在 create table 的时候, 不指定引擎,就是 InnoDB 22 | 23 | 也可以在 create table 的时候 使用语句 engine = memory 来指定使用内存引擎创建表 24 | 25 | --- 26 | 27 | ## 2. 连接器 28 | 29 | 1. 首先,需要连接到数据库上, 使用连接器跟客户端建立连接,获取权限等。 30 | 31 | ```sql 32 | mysql -h -P -u root -p 33 | 34 | ``` 35 | 36 | -h : 后面接 远端服务器 ip 地址 37 | 38 | -P : 后面接 端口号 39 | 40 | 41 | 2. 连接完成之后,没有后续的命令, 连接就处于空闲状态, 默认超过 8 小时自动断开连接 42 | 43 | ```sql 44 | mysql> show processlist; 45 | +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ 46 | | Id | User | Host | db | Command | Time | State | Info | 47 | +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ 48 | | 4 | event_scheduler | localhost | NULL | Daemon | 33233 | Waiting on empty queue | NULL | 49 | | 8 | root | localhost | NULL | Query | 0 | starting | show processlist | 50 | +----+-----------------+-----------+------+---------+-------+------------------------+------------------+ 51 | 2 rows in set (0.00 sec) 52 | 53 | ``` 54 | 55 | 3. 数据库连接分为 长连接和短连接 56 | 57 | * 长连接 : 客户端持续有请求, 一直使用同一个连接 58 | * 短连接 : 每次执行完几次查询就断开连接, 下次查询再建立一个 59 | 60 | **建立连接过程复杂,但是一直使用长连接,占用内存会特别大,会被系统强行杀掉(OOM), 导致 MySQL 异常重启** 61 | 62 | solve: 63 | 64 | * 定期断开长连接 65 | * 执行 mysql_reset_connection 重新初始化连接资源(不需要重连和重新权限验证) 66 | 67 | ---- 68 | 69 | ## 3. 查询缓存 70 | 71 | 建立连接之后, 执行语句 72 | 73 | MySQL 接收到查询请求之后,会先到 查询缓存之中查找是否存在查询语句, 如果存在,,直接返回到客户端 74 | 75 | 查询缓存 保存之前执行过的语句 以 key-value 对的形式储存 76 | 77 | **查询缓存往往弊大于利** 78 | 79 | 只要表存在一个更新,标上所有的查询缓存都会清空,所以如果数据库经常更新, 查询缓存的命中率会特别低 80 | > 除非数据库表是一个 静态的表 81 | 82 | 83 | **对于 MySQL 8.0 不存在 查询缓存的功能** 84 | 85 | --- 86 | 87 | 88 | ## 4. 分析器 89 | 90 | MySQL 需要对 SQL语句进行解析 91 | 92 | 1. 先会做 “词法分析” 93 | 94 | * 输入是多个字符串和空格组成,先要识别出其中的字符串分别是什么 95 | 96 | * 识别关键字 select table id 等 97 | 98 | * 验证 表名 和 字段名 99 | 100 | 2. 进行 “语法分析” 101 | 102 | * 判断是否满足 SQL 语法 103 | 104 | 105 | ----- 106 | 107 | ## 5. 优化器 108 | 109 | 经过分析器之后,MySQL 知道需要做什么, 在执行之前,需要优化处理 110 | 111 | 112 | 表内存在多个索引的时候, 决定使用哪一个,或者存在多表关联,决定连接顺序 113 | 114 | 不同方案执行的效率不同,优化器就是进行方案选择 115 | 116 | 117 | ---- 118 | 119 | ## 6. 执行器 120 | 121 | 开始执行语句 122 | 123 | 1. 首先会判断对 要执行的表是否有查询权限 124 | 125 | 没有权限会报错 126 | 127 | ```sql 128 | mysql> select * from T where ID=10; 129 | 130 | ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T' 131 | 132 | ``` 133 | 134 | 2. 如果有权限,就会打开表,执行流程 135 | 136 | 2-1 如果没有索引 137 | 138 | * 调用 InnoDB 引擎接口调取表的第一行,判断 ID 是不是 10 , 不是就跳过,是就储存在 结果集之中 139 | 140 | * 调用 InnoDB 引擎接口调取表的 下一行,重复操作,直到最后一行 141 | 142 | * 结果返回到客户端 143 | 144 | 145 | 2-2 如果存在索引的表 146 | 147 | * 调用 满足条件的第一行 接口 148 | 149 | * 之后循环 满足条件的下一行 接口,(这些接口在引擎中已经定义好) 150 | 151 | 152 | --- 153 | 154 | ## 7. 思考题 155 | 156 | 如果执行语句 157 | ```sql 158 | select * from T where k = 1; 159 | ``` 160 | 数据库表中没有 k 这个字段,执行会报错 161 | 162 | 这个报错会出现在 分析器阶段, 分析器会验证表名和字段名 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Database/MySQL 日志系统.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 丁奇老师 的《 MySQL 实战45讲》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 更新语句的执行流程 6 | 7 | ```sql 8 | 9 | update T set c = c+ 1 where ID = 2 ; 10 | ``` 11 | 12 | 13 | 执行流程,类似于上一篇笔记中介绍的查询流程 14 | 15 | ![](https://i.loli.net/2019/07/15/5d2c80370199a68830.png) 16 | 17 | 18 | 1. 连接数据库 19 | 20 | 2. 因为要更新数据表,所以和表相关的查询缓存都会失效, 更新命令就会清空所有的缓存结果 21 | 22 | 3. 分析器 通过 词法和语法的分析知道是一条更新语句 23 | 24 | 4. 优化器 确定使用 ID 的索引 25 | 26 | 5. 执行器开始执行 更新操作 27 | 28 | 6. 除了上述和查询流程相同的语句, **更新还会涉及两个日志模块 : redo log 和 binlog** 29 | 30 | 31 | 32 | --- 33 | 34 | ## 2. 日志模块 : redo log 35 | 36 | 如果每次更新操作都要写进磁盘, 磁盘需要找到相应的记录,再进行更新,整个过程的 IO 成本,查找成本都是很高。 37 | 38 | MySQL 为了提高更新的效率, 使用 Write-Ahead logging 技术: 先写入日志, 之后再写进磁盘 39 | 40 | 41 | 1. 存在记录需要更新的时候, InnoDB 引擎就会把记录写到 redo log里面,并更新内存 42 | 43 | 2. 在系统空闲的时候, InnoDB 引擎将操作记录更新到磁盘里面 44 | 45 | 3. 其中 redo log 的大小是固定的,写满了之后就不能再执行更新了, 需要把记录更新到磁盘里面,再擦除一些记录。 46 | 47 | 4. 存在 redo log , InnoDB 保证数据库存在异常的时候, 之前的记录还保存, 存在 crash-safe 能力 48 | 49 | 50 | **redo log 记录数据页 做了什么改动** 51 | 52 | 53 | --- 54 | 55 | ## 3. binlog --- 归档日志 56 | 57 | redo blog 是 InnoDB 的日志, binlog 是 Sever 层的日志 58 | 59 | > 存在两份日志的原因: MySQL 以前的引擎是 MyISAM 不存在 crash-safe 的能力。 InnoDB引擎是以插件形式引入到 MySQL, 使用另一套日志系统 来实现 crash- safe 60 | 61 | 62 | 63 | * binlog 所有的引擎都可以使用, redo log 只有 InnoDB 可以使用 64 | 65 | * redo log 记录的是物理日志 : 记录某个数据页面修改了什么; binlog 逻辑日志, 记录 语句的原始逻辑 66 | 67 | * redo 是固定大小,循环覆盖的, binlog 是可以追加写入,文件到一定的大小,会切换到下一个,覆盖之前的日志 68 | 69 | 70 | **binlog 存在两种模式, statement 记录的是sql 语句; row 格式 记录更新前和更新后的 行的内容** 71 | 72 | ----- 73 | 74 | ## 4. 执行 UPDATE 的内部流程 75 | 76 | ```sql 77 | 78 | update T set c = c+ 1 where ID = 2 ; 79 | ``` 80 | 81 | 82 | 1. 执行期先找到 找到 ID =2 的行, 如果这一行所在的数据在内存之中,直接返回到执行器; 如果不在,需要先从磁盘读取到内存之中,再返回到执行器 83 | 84 | 2. 执行器获得数据之后, 更新数据的值,再调用引擎接口写入这行新的数据 85 | 86 | 3. 引擎将新的数据更新到内存之中, 更新的操作记录记录到 redo log, 此时 redo log 处于 prepare 状体啊 87 | 88 | 4. 执行器生成这个操作的 binlog ,把binlog 写入磁盘 89 | 90 | 5. 执行器调用引擎的 提交事务接口, 引擎把 redo log 改成 commit 状态 91 | 92 | --- 93 | 94 | ## 5. 两阶段 提交 95 | 96 | redo log 的提交分为 prepare 和 commit 两部分 97 | 98 | 99 | 数据库误删 的数据恢复 : 100 | 101 | 1. 找到一个全量备份, 从这个备份中恢复到临时库 102 | 103 | 2. 将备份的 binlog 一次提取出来, 重放到误删之前的 104 | 105 | 106 | 107 | 如果不是两阶段提交, , 假如写完第一个日志之后 就发生了 crash 108 | 109 | 110 | 111 | 1. 先写 redo ,再写 bin : 112 | 113 | redo log 可以把数据恢复过来 ,恢复过来的数据和原库的相同; 114 | 但是由于 binlog 没有写入, binlog 没有相应的语句, 如果使用 binlog 恢复 临时库, 就会和原库的值不同 115 | 116 | 2. 先写 binlog , 再写 redo log 117 | 118 | binlog 写入之后 crash ,由于 redo log 没有写入 ,这个事务无效, 数据库值没有发生改变,但是 binlog 记录了 更新命令的日志, 使用 binlog 恢复就会多出来一个 没有执行的事务,与原库的值不相同。 119 | 120 | 121 | **扩容的时候也需要恢复临时库**: 常见的做法是 全量备份加上应用 binlog 实现 122 | 123 | 124 | 125 | **两阶段提交让两个状态 保持逻辑上的一致** 126 | 127 | 128 | ---- 129 | 130 | 131 | ## 6. 参数设定 132 | 133 | innodb_flush_log_at_trx_commit 参数设定为 1 : redo log 直接持久化到 磁盘 134 | 135 | sync_binlog 参数设定为1 , 每次事务的 binlog。持久化到磁盘 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /Database/Python 中使用 MySQL.md: -------------------------------------------------------------------------------- 1 | ## 0. Python 数据库 API 规范 2 | 3 | 各种数据库提供统一的访问接口, 在切换数据库的时候, Python 层的代码改动较小 4 | 5 | ![](https://i.loli.net/2019/07/20/5d32c4bf3fad111251.png) 6 | 7 | 8 | 1. 引入 API 模块 9 | 10 | 2. 和数据库建立连接 11 | 12 | 3. 执行 SQL 语句 13 | 14 | 4. 关闭数据库连接 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ## 1. 安装 MySQL 驱动 23 | 24 | 官方提供的 驱动器 25 | 26 | ``` 27 | pip install mysql-connector-python 28 | ``` 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ## 2. 连接到数据库 37 | 38 | 1. 操作数据库表, 需要先连接数据库, 数据库的连接称为 connection 39 | 40 | ```python 41 | 42 | import mysql.connector 43 | conn = mysql.connector.connect(user="root",password = "****",database = "students") 44 | ``` 45 | 46 | > 密码更换成自己的数据库密码, database 跟换成自己创建的数据库名 47 | 48 | * 指定 host user, password,port 等参数创建数据库连接 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 2. 连接到数据库后,需要打开游标,称之为Cursor,。 57 | 58 | ```python 59 | cursor = conn.cursor() 60 | 61 | ``` 62 | 63 | 64 | 3. 通过Cursor执行SQL语句,然后,获得执行结果 65 | 66 | > 创建一个数据 名字 user 表 67 | ```python 68 | cursor.execute('create table user (id varchar(20) primary key, name varchar(20))') 69 | ``` 70 | * SQL 语句和 之前 SQL 相关文章中介绍的基本相同 71 | 72 | 73 | ```python 74 | 75 | cursor.fetchall() # 读取数据集中的所有行, 返回一个元组 类型 76 | cursor.fetchone() # 读取数据集中的一条数据 77 | cursor.fetchmany(n) # 读取数据集中的多条数据, 返回一个元组 类型 78 | 79 | 80 | 81 | ``` 82 | 83 | varchar : 84 | 85 | > char类型是使用固定长度空间进行存储,范围0-255。比如CHAR(30)能放30个字节,存放abcd时,尾部会以空格补齐,实际占用空间 30bytes 。检索它的时候尾部空格会被去除。char善于存储经常改变的值,或者长度相对固定的值,比如type、ip地址或md5之类的数据,不容易产生碎片。关于它的效率可以参考这里。 86 | 87 | > varchar类型保存可变长度字符串,范围0-65535(但受到单行最大64kb的限制)。比如用varchar(30)去存放abcd,实际使用5个字节,因为还需要使用额外1个字节来标识字串长度(0-255使用1个字节,超过255需要2个字节)。varchar善于存储值的长短不一的列,也是用的最多的一种类型,节省磁盘空间。update时varchar列时,如果新数据比原数据大,数据库需要重新开辟空间,这一点会有性能略有损耗,但innodb引擎下查询效率比char高一点。这也是innodb官方推荐的类型。 88 | 89 | 90 | 4. 插入一行记录, 使用 %s 作为占位符 91 | 92 | ```python 93 | cursor.execute('insert into user (id, name) values (%s, %s)', ['1', 'Michael']) 94 | ``` 95 | 96 | 97 | 5. 操作之后, 使用 commit 提交 98 | 99 | ```python 100 | conn.commit() 101 | cursor.close() 102 | 103 | 104 | ``` 105 | 106 | 107 | 6. 完整插入数据的操作 108 | 109 | 110 | ```python 111 | import mysql.connector 112 | conn = mysql.connector.connect(user="root",password = "@52zxw1314",database = "students") 113 | 114 | cursor = conn.cursor() 115 | cursor.execute("SELECT * FROM students") 116 | cursor.fetchall() 117 | # 查看现有的 表的数据 118 | 119 | #### 120 | 121 | [(1, 'liu', 100, 'male'), (2, 'lin', 80, 'male'), (4, 'li', 100, 'male')] 122 | 123 | cursor.execute("DESC students") 124 | cursor.fetchall() 125 | ##### 查看现有表的字段##### 126 | [('id', 'int(11)', 'NO', 'PRI', None, ''), 127 | ('sname', 'char(10)', 'NO', '', None, ''), 128 | ('score', 'int(11)', 'NO', '', None, ''), 129 | ('gender', 'char(6)', 'NO', '', None, '')] 130 | 131 | 132 | # 新增一个人 133 | 134 | sql = "INSERT INTO students(id,sname,score,gender) VALUES(%s, %s,%s,%s)" 135 | ## 统一使用 s% 作为占位符 136 | 137 | val = (5,"zou",99,"female") 138 | cursor.execute(sql,val) 139 | 140 | # 提交更改 141 | conn.commit() 142 | 143 | ## 查询更改后的数据库表 144 | 145 | cursor.execute("SELECT * FROM students") 146 | data = cursor.fetchall() 147 | for student in data: 148 | print(student) 149 | 150 | ##### 查询结果 151 | 152 | (1, 'liu', 100, 'male') 153 | (2, 'lin', 80, 'male') 154 | (4, 'li', 100, 'male') 155 | (5, 'zou', 99, 'female') 156 | 157 | ### 按照我们的想法 增加了一个数据 158 | 159 | ``` 160 | 161 | 7. 修改 数据库表的数据 162 | 163 | ```python 164 | sql = "UPDATE students SET score = %s WHERE sname = %s" 165 | val = (90,"liu") 166 | cursor.execute(sql,val) 167 | 168 | conn.commit() 169 | cursor.execute("SELECT * FROM students") 170 | data = cursor.fetchall() 171 | for student in data: 172 | print(student) 173 | 174 | 175 | ### 修改结果 176 | (1, 'liu', 90, 'male') 177 | (2, 'lin', 80, 'male') 178 | (4, 'li', 100, 'male') 179 | (5, 'zou', 99, 'female') 180 | 181 | ``` 182 | 183 | 184 | 8. 执行完了之后,关闭数据库的连接 185 | 186 | ``` 187 | cursor.close() 188 | conn.close() 189 | 190 | ``` 191 | 192 | 193 | --- 194 | 195 | ## 3. 数据库操作异常检查 196 | 197 | 198 | ```python 199 | 200 | import traceback 201 | try: 202 | sql = "INSERT INTO students(id,sname,score,gender) VALUES(%s, %s,%s,%s)" 203 | val = (6,"wen",89,"female") 204 | cursor.execute(sql,val) 205 | conn.commit() 206 | print(cursor.rowcount," 插入 成功") 207 | except Exception as e: 208 | traceback.print_exc() 209 | conn.rollback() 210 | finally: 211 | conn.close() 212 | 213 | ####### 214 | 215 | 1 插入 成功 216 | 217 | ##### 218 | 219 | conn = mysql.connector.connect(user="root",password = "@52zxw1314",database = "students") 220 | cursor = conn.cursor() 221 | cursor.execute("SELECT * FROM students") 222 | data = cursor.fetchall() 223 | for student in data: 224 | print(student) 225 | 226 | ########### 227 | 228 | (1, 'liu', 90, 'male') 229 | (2, 'lin', 80, 'male') 230 | (4, 'li', 100, 'male') 231 | (5, 'zou', 99, 'female') 232 | (6, 'wen', 89, 'female') 233 | 234 | 235 | ``` 236 | 237 | 238 | ---- 239 | 240 | # 参考 241 | 242 | 1. https://www.liaoxuefeng.com/wiki/1016959663602400/1017802264972000 243 | 244 | 2. https://segmentfault.com/a/1190000005124235 245 | -------------------------------------------------------------------------------- /Database/SQL 关系数据库概述.md: -------------------------------------------------------------------------------- 1 | 本文为 廖雪峰老师 SQL教程 学习笔记 2 | https://www.liaoxuefeng.com/wiki/1177760294764384 3 | 4 | ----- 5 | 6 | ## 1. SQL 基本 7 | 8 | 1. SQL : 结构化查询语言,用来访问和操作数据库系统 9 | 10 | 2. SQL语言 定义了集中操作数据库的能力: 11 | 12 | * DDL : Data Definition Language 13 | 14 | 用户定义数据 : 创建表,删除表, 修改表结构 15 | 16 | * DML: Data Manipulation Language 17 | 18 | 用户 添加, 删除, 更行数据的 能力 19 | 20 | * DQL:Data Query Language 21 | 22 | 允许用户查询数据, 23 | 24 | 25 | 3. 语法特点 : 关键字不区分大小写 26 | 27 | ---- 28 | 29 | ## 2. 关系模型 30 | 31 | 关系模型本质上是若干个储存数据的二维表。 32 | * 表的每一行称作 record 记录, 记录数据,一条记录是由多个字段组成的 33 | * 每一列称作 字段 34 | 35 | 字段定义了 数据类型, 以及是否允许 null 。 NULL 表示数据不存在 36 | > 通常情况下,应该避免允许 NULL ,可以简化查询条件, 加快查询的速度,读取数据后无需判断是否为 NULL 37 | 38 | 39 | ### 1. 主键 40 | 41 | 对于关系表,任意两条记录不能重复,能够通过某个字段区分出不同的记录,这个字段称为 主键 42 | 43 | 例如: 44 | 45 | | id | name | score | 46 | | :-----| ----: | :----: | 47 | | 1 | liu | 90 | 48 | | 2 | zou | 95 | 49 | 50 | 如果把 name 字段设定为主键, 通过名字 liu, zou 就可以确定一条记录, 之后不能储存相同名字的同学 51 | 52 | **对于主键, 记录一旦插入到表之中,主键最好不要在进行修改** 53 | 54 | 不使用任何业务相关的字段作为主键: 这个字段一般命名为 id, 常见的 id 字段类型: 55 | > 对用户没有任何意义的数据 , 任何含有业务含义的列都有改变的可能性,业户的改变会导致很大的维护开销 56 | 57 | * 自增整数类型, 数据库在插入数据的时候会自动的微每一条记录分配一个自增整数 58 | > BIGINIT 自增类型允许 922亿亿记录 59 | 60 | * GUID 类型, 通过 网卡 MAC 地址,时间戳和随机数保证任意计算机在任意时间生成的字符串都是不一样的 61 | 62 | ---- 63 | 64 | ### 2. 联合主键 65 | 66 | 通过多个字段 唯一标识记录, 两个或者更多的字段都设置为主键 --- 联合主键 67 | 68 | **联合主键只要主键不完全相同就允许** 69 | 70 | 尽量不使用联合主键 71 | 72 | ---- 73 | 74 | ### 3. 外键 实现一对多的关系 75 | 76 | 1. 通过字段 可以将数据与另一张表关联起来 77 | 78 | students 表 79 | 80 | 81 | | id | name | score | 82 | | :-----| ----: | :----: | 83 | | 1 | liu | 90 | 84 | | 2 | zou | 95 | 85 | 86 | 87 | clsses 表 88 | 89 | | id | name | other | 90 | | :-----| ----: | :----: | 91 | | 1 | 一班 | ... | 92 | | 2 | 二班 | ... | 93 | 94 | 95 | 为了 确定 学生属于哪个班级, 在 students 表中加入 class_id 96 | 97 | 98 | | id | name | class_id | 99 | | :-----| ----: | :----: | 100 | | 1 | liu | 1 | 101 | | 2 | zou | 2 | 102 | |3| zhang| 1| 103 | 104 | class_id 就将studens 和 classes 表关联起来 105 | 106 | 107 | 2. 外键 通过定义外键约束 实现 108 | 109 | 110 | ```sql 111 | AFTER TABLE students 112 | ADD CONSTRAINT fk_class_id # 外键约束名称, 113 | FOREIGN KEY (class_id) # 指定 class_id 作为 外键 114 | REFERENCES classes (id); # 指定 外键 关联到 classes 的 id 列, 主键列 115 | ``` 116 | 117 | * 外键约束会降低数据库的性能 118 | 119 | * 删除外键约束 120 | 121 | ```sql 122 | AFTER TABLE students 123 | DROP FOREIGN KEY fk_class_id; 124 | ``` 125 | 126 | 127 | 128 | 3. 中间表 实现多对多关系 129 | 130 | teachers 131 | 132 | | id | name | 133 | | :-----| ----: | 134 | | 1 | 刘老师 | 135 | | 2 | 邹老师 | 136 | | 3| 张老师 | 137 | 138 | 139 | 140 | classes : 141 | 142 | | id | name | 143 | | :-----| ----: | 144 | | 1 | 一班 | 145 | | 2 | 二班 | 146 | 147 | 148 | 中间表 149 | 150 | 151 | | id | teacher_id| class_id | 152 | | :-----| ----: | ----: | 153 | | 1 | 1 | 1 | 154 | | 2 | 1 | 2 | 155 | | 3| 2 | 1| 156 | | 4 | 3 | 1| 157 | | 4 | 3 | 2 | 158 | 159 | 外键: 中间表上的两个字段都要设置 外键 160 | 161 | 162 | 163 | 4. 一对一 164 | 165 | 一对一的表相当于 表增加一个 列 166 | 167 | 一些应用 会把一个大的表拆分成两个 一对一的表, 把经常读取喝不经常读取的字段分开,获取更高的性能 168 | 169 | 170 | ---- 171 | 172 | ### 4. 索引 173 | 174 | 175 | 索引:关系数据库对于某一列或者多个列进行预排列的数据结构。之后使用索引,查询的时候不必扫描整个数据库,定位到符合条件。 176 | 177 | 无论是否创建索引, 都可以进行数据库查询, 只是查询的速度存在差异 178 | 179 | 180 | | id | name | score | gender | 181 | | :-----| ----: | :----: | : ---: | 182 | | 1 | liu | 90 | M | 183 | | 2 | zou | 95 | F| 184 | 185 | 186 | 1. 经常根据 score 查询, 对 score 列创建索引 187 | 188 | ```sql 189 | AFTER TABLE students 190 | ADD INDEX id_score(score); 191 | ``` 192 | 创建了一个 名称 id_score 索引是 score 的索引 193 | 194 | 195 | 2. 创建多列的索引 196 | ```sql 197 | AFTER TABLE students 198 | ADD INDEX id_score(name, score); 199 | 200 | ``` 201 | 202 | * 索引值越散列 , 索引的效率越高 203 | 204 | * 索引的 优点: 提高了查询的效率, 205 | 206 | * 索引的 缺点 : 插入,更新,删除的时候, 需要修改 索引 207 | 208 | **主键数据库会自动创建主键索引** 209 | 210 | 211 | 3. 唯一索引 212 | 213 | 身份证号,邮箱地址, 唯一的列,但是由于具有业务含义, 不适合做主键,但是具有唯一性的约束 214 | 215 | ```sql 216 | AFTER TABLE students 217 | ADD UNIQUE INDEX id_score(name); 218 | ``` 219 | 这里假设名字不可重复, 这样就添加了一个 唯一索引。 220 | 221 | 222 | 223 | ---- 224 | # 参考 225 | 226 | 1. https://blog.csdn.net/cxzhq2002/article/details/4435267 227 | 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /Machine_Learning/Attention 机制理解(1) --- Seq2Seq 中的 attention.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/gbc10.jpg) 2 | 3 | 4 | ---- 5 | 6 | ### 1. Seq2Seq 简介 7 | 8 | Seq2Seq 包含两部分 Encoder 和 Decoder, 9 | 10 | 1. Encoder-Decoder结构先将输入数据编码成一个上下文向量c: 11 | 12 | * 最简单的方法就是把Encoder的最后一个隐状态赋值给c 13 | 14 | * 还可以对最后的隐状态做一个变换得到c, 15 | 16 | * 也可以对所有的隐状态做变换 17 | 18 | 2. 拿到c之后,就用另一个RNN网络对其进行解码 19 | 20 | * c当做之前的初始状态h0输入到Decoder 21 | 22 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/2kf3o.jpg) 23 | 24 | * c当做每一步的输入 : 25 | 26 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/nl4sg.jpg) 27 | 28 | 29 | 观察 下图对比发现, Decoder 的公式和 RNN 几乎一样,只是 Decoder的公式中 多了一个 C 30 | 31 | C 指的是 **context vector** 包含所有输入信息的向量,在 Encoder中的 **hidden state** 32 | 33 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/717nd.jpg) 34 | 35 | 36 | Encoder将输入句压缩成固定长度的context vector,context vector即可完整表达输入句,再透过Decoder将context vector内的信息产生输出句。 37 | 38 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ufygd.jpg) 39 | 40 | ### 2. seq2seq 远离展示 -- 动图 41 | 42 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ai2o6.gif) 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ---- 59 | 60 | ### 3. 注意力模型 61 | 62 | 如果句子很长,使用固定长度的 context vector 效果不好,引入 注意力模型 63 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/rhl8o.jpg) 64 | 65 | 66 | **对输入句的每一个文字都创建一个 context vector**,而不是值从最终的 hidden state 获得一个 context vector。 67 | 68 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/2d7ik.jpg) 69 | 70 | 71 | 观察上图,可以知道,**关键就是如何计算 $c_{i}$** 72 | 73 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/s9lrk.jpg) 74 | 75 | 其中 $\alpha_{i,j}$ 是**attention score**衡量输入句中每个文字对目标句每个文字所带来的重要性的程度 76 | 77 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/hzsqn.jpg) 78 | 79 | attention score由score $e_{ij}$ 求得 80 | 81 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/hm9sq.jpg) 82 | 83 | 其中 a 是根据输入字位置 j 和输出字位置 i 这两者的关联程度(decoder中的hidden state s_{i-1}和输入句中的第j个文字hidden state h_{j}的关系所计算出的权重 ),常见形式有: 84 | 85 | * 点乘 $\vec{e_t}=\vec{s_{t-1}}^T\vec{h}$ 86 | 87 | * 加权点乘 88 | 89 | * 加和 90 | 91 | ---- 92 | 1. 得到$e_{ij}$后 进行softmax操作将其 normalize 得到 attention score 的分布 93 | 94 | 2. 利用 attention score 可以计算 context vector 95 | 96 | 3. 计算 decoder的 下一个 hidden state $s_t = f(s_{t-1},y_{t-1},c_t)$ 和 该位置的输出 $p(y_t|y_1,...,y_{t-1}, \vec{x}) = g(y_{i-1}, s_i, c_i)$ 97 | 98 | --- 99 | 100 | 其中 context vector 又称为 attention vector 101 | 102 | 可以将 attention score 列为矩阵,透过此矩阵可看到输入端文字和输出端文字间的对应关系 103 | 104 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/q9sbr.jpg) 105 | 106 | 107 | ---- 108 | 109 | ### 4. 注意力机制原理动图 110 | 111 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0p5oj.gif) 112 | 113 | 注意力机制区别于传统的 Seq2Seq 114 | 115 | * encoder 传递所有的 hidden state 到 decoder 116 | 117 | * decoder 歪了 focus on 最和自己相关的部分,需要额外做一步 118 | 119 | * 给 每一个 隐藏态一个 score 120 | * 将每个隐藏状态乘以 softmaxed 之后的分数,从而放大分数高的隐藏状态,淹没分数低的隐藏状态 ,最终获得 context 121 | 122 | 123 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/nyse1.gif) 124 | 125 | 126 | 127 | * 经过attention 获得 新的 h 之后,将 h 和 c 拼接成一个向量 输入到前馈神经网络 ?? 128 | 129 | * 前馈神经网络的输出表示该时间步长的输出单词 130 | 131 | * 重复该过程。 132 | 133 | 134 | 135 | 136 | 137 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/167gk.gif) 138 | 139 | 140 | ---- 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | # 参考 154 | 155 | 1. 从Seq2seq到Attention模型到Self Attention(一)--- https://mp.weixin.qq.com/s/7Kxnmaoh10hrM6VpQj3ZQA 156 | 157 | 2. 完全图解RNN、RNN变体、Seq2Seq、Attention机制--https://zhuanlan.zhihu.com/p/28196873 158 | 159 | 160 | 3. 深度学习中的注意力机制(2017版)---https://blog.csdn.net/malefactor/article/details/78767781 161 | 162 | 4. Seq2seq pay Attention to Self Attention: Part 1 --- https://medium.com/@bgg/seq2seq-pay-attention-to-self-attention-part-1-d332e85e9aad 163 | 164 | 5. Visualizing A Neural Machine Translation Model (Mechanics of Seq2seq Models With Attention) ---https://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/ 165 | -------------------------------------------------------------------------------- /Machine_Learning/KNN简单实现.md: -------------------------------------------------------------------------------- 1 | * 原项目 link --- https://github.com/Avik-Jain/100-Days-Of-ML-Code/blob/master/Code/Day%2011%20K-NN.md 2 | 3 | **本文是对原文的额一个汉化,以及相应的内容补充** 4 | 5 | * GitHub 项目 link --- https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day7-8-9-10KNN/README.md 6 | 7 | ---- 8 | 9 | 10 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/skyde.jpg) 11 | 12 | --- 13 | 14 | 15 | 16 | 17 | 18 | ## KNN 算法工作简介 19 | 20 | * 主要: 对未标记的对象进行标记 21 | * 计算实例点与标记的对象之间的距离,确定其k近邻点 22 | * 使用周边数量最多的类标签来确定该对象的标签 23 | 24 | > KNN基础学习详见--> https://github.com/LiuChuang0059/Machine_Learning/blob/master/Statical_Learning/Chapter_3-KNN/README.md 25 | 26 | 27 | 28 | ## KNN算法实现 29 | 30 | ### 1 数据 31 | 32 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ntbsw.jpg) 33 | 34 | 35 | ------------------- 36 | ------------------- 37 | 38 | 39 | 40 | ### 2 算法实现 41 | 42 | #### Importing the libraries 43 | 44 | ```python 45 | 46 | import numpy as np 47 | import matplotlib.pyplot as plt 48 | import pandas as pd 49 | ``` 50 | 51 | #### Importing the dataset 52 | ```python 53 | dataset = pd.read_csv('Social_Network_Ads.csv') 54 | X = dataset.iloc[:, [2, 3]].values 55 | y = dataset.iloc[:, 4].values 56 | ``` 57 | 58 | #### Splitting the dataset into the Training set and Test set 59 | ```python 60 | from sklearn.cross_validation import train_test_split 61 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0) 62 | 63 | ``` 64 | 65 | 66 | #### Feature Scaling 67 | ```python 68 | from sklearn.preprocessing import StandardScaler 69 | sc = StandardScaler() 70 | X_train = sc.fit_transform(X_train) 71 | X_test = sc.transform(X_test) 72 | ``` 73 | 74 | #### Fitting K-NN to the Training set 75 | ```python 76 | from sklearn.neighbors import KNeighborsClassifier 77 | classifier = KNeighborsClassifier(n_neighbors = 5, metric = 'minkowski', p = 2) 78 | classifier.fit(X_train, y_train) 79 | 80 | ``` 81 | 82 | #### Predicting the Test set results 83 | ```python 84 | 85 | y_pred = classifier.predict(X_test) 86 | ``` 87 | 88 | 89 | #### visualisation-------详见--->[Lpgistic_regression](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day4-5-6_Logistic_regression/README.md#step-5-visulisation) 90 | 91 | ```python 92 | plot_decision_regions(X_test, y_pred, classifier=cl) 93 | plt.title("Test set") 94 | ``` 95 | 96 | ## 结果 97 | 98 | 99 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/4kvzi.jpg) 100 | 101 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/pk49j.jpg) 102 | 103 | ------------------ 104 | 105 | # 附 106 | 107 | ### [完整代码](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day7-8-9-10KNN/KNN.py) 108 | 109 | ### [数据集](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day7-8-9-10KNN/Social_Network_Ads.csv) 110 | 111 | 112 | 113 | # 问题 114 | - [ ] 尝试自实现knn分类算法 115 | 116 | - [ ] 改变调整参数---效果 117 | 118 | 119 | 120 | 121 | # 参考 122 | 123 | 1. KNeighborsClassfier参数: 124 | http://sklearn.apachecn.org/cn/0.19.0/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier 125 | 126 | 2. KNeighborsClassfier使用 : http://sklearn.apachecn.org/cn/0.19.0/auto_examples/neighbors/plot_classification.html#sphx-glr-auto-examples-neighbors-plot-classification-py 127 | 128 | 129 | 3. KNN 算法python实现 : https://www.cnblogs.com/ybjourney/p/4702562.html 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Machine_Learning/Keras 储存和载入训练好的模型.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 训练好的模型使用 save weights 保存权重: 4 | 5 | 因为自定义损失函数之后,使用 save model 会出错,修改起来比较麻烦(搞了很久没有解决) 6 | 7 | 8 | ```python 9 | model.save_weights('test%d.h5'%(i+1)) 10 | ``` 11 | 12 | 再次导入 使用 13 | 14 | ```python 15 | model.load_weights('test10.h5',by_name= True) 16 | 17 | ``` 18 | 19 | **但是直接导入会报错** 20 | 21 | ---- 22 | 23 | 24 | **Solve:** 25 | 26 | 1. 首先构建一个 完全相同的模型 之后compile ,这时候导入 就可能出现: 27 | 28 | ```python 29 | expects 0 weight(s), but the saved weights have 6 element(s) 30 | ``` 31 | 32 | 2. 我的 较笨但是在我这里有效的办法: compile 模型之后, 训练模型 1个 epoch 33 | 34 | ```python 35 | model.fit() 36 | ``` 37 | 38 | 3. 之后再导入 权重,就没有报错,结果和训练好的模型相同 39 | ```python 40 | model.load_weights('test10.h5',by_name= True) 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /Machine_Learning/TensorFlow Probability 中的结构化时间序列模型.md: -------------------------------------------------------------------------------- 1 | 原文 : Structural Time Series modeling in TensorFlow Probability by Dave Moore, Jacob Burnim, and the TFP Team 2 | 3 | link : https://medium.com/tensorflow/structural-time-series-modeling-in-tensorflow-probability-344edac24083 4 | 5 | 6 | ---- 7 | 8 | 主要介绍 tfp.sts 这个 library , 进行时间序列预测 9 | 10 | 11 | ## 1. Structural Time Series (STS) models 12 | 13 | 结构化时间序列模型是一组应用到时间序列的概率模型, 包括很多标准时间序列模型思想。 14 | 15 | * 自回归过程 16 | 17 | * 移动平均 18 | 19 | * local linear trends 20 | 21 | * 季节性 22 | 23 | * regression and variable selection on external covariates (other time series potentially related to the series of interest). 24 | 25 | 26 | 一个 STS 模型可以看作是上面各种特性成分的加和。 27 | 28 | 结构化时间序列通常可以从相对较少的数据(例如,只有一个包含数十个点的输入序列)中产生合理的预测。模型的假设是可解释的,我们可以通过可视化将过去的数据和未来的预测分解为结构组件来解释预测。此外,结构时间序列模型使用概率公式,可以自然地处理丢失的数据,并提供有原则的不确定性量化。 29 | 30 | ---- 31 | 32 | ## 2. Structural Time Series in TensorFlow Probability 33 | 34 | TensorFlow Probability (TFP) 现在支持 : 利用变分推理(VI)和哈密顿蒙特卡罗(HMC)对模型参数进行贝叶斯推理,计算点预测和预测不确定性。 35 | 36 | 因为这些内置在 tensorflow 中, 这些方法可以并行化处理 , 也可以和深度神经网络进行集成。 37 | 38 | ---- 39 | 40 | ## 3. 实例 : Forecasting CO2 Concentration 41 | 42 | ![](https://i.loli.net/2019/08/29/OXLsuZity13NfaS.png) 43 | 44 | 进过观察可以发现上面的时序数据既有一个长期的趋势又有一定的周期性。 我们可以直接将这两个特性编码到 结构化时间序列模型, 使用 TFP 45 | 46 | ```python 47 | import tensorflow_probability as tfp 48 | trend = tfp.sts.LocalLinearTrend(observed_time_series=co2_by_month) 49 | seasonal = tfp.sts.Seasonal( 50 | num_seasons=12, observed_time_series=co2_by_month) 51 | model = tfp.sts.Sum([trend, seasonal], observed_time_series=co2_by_month) 52 | 53 | ``` 54 | 55 | 这里我们使用了一个局部线性趋势模型,它假设趋势是线性的,随着时间的推移,斜率随随机游走缓慢地演化。将模型与数据进行拟合,得到基于我们建模假设的概率预测: 56 | 57 | ![](https://i.loli.net/2019/08/29/Pyf9TZcgsezFLpj.png) 58 | 59 | 可以看出,随着线性趋势模型对斜率外推的信心降低,预测的不确定性随着时间的推移而增加。平均预测结合了季节变化和现有趋势的线性外推,真实值在95%的预测区间内。 60 | 61 | 62 | 63 | **[完整代码](https://github.com/tensorflow/probability/blob/master/tensorflow_probability/examples/jupyter_notebooks/Structural_Time_Series_Modeling_Case_Studies_Atmospheric_CO2_and_Electricity_Demand.ipynb)** 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Machine_Learning/keras 模型结构可视化.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0o5yi.jpg) 2 | 3 | --- 4 | 5 | ### 1. 安装 Graphviz 6 | 7 | ```python 8 | brew install graphviz 9 | ``` 10 | 11 | 12 | ```python 13 | pip install graphviz 14 | ``` 15 | 16 | 17 | ```python 18 | pip install pydot_ng 19 | ``` 20 | 21 | Go to keras/utils/vis_util.py (this is the file showing error) 22 | You will see something like this. 23 | 24 | 25 | ```python 26 | try: 27 | import pydot 28 | except ImportError: 29 | pydot = None 30 | ``` 31 | Change import pydot to **import pydot_ng as pydot** 32 | 33 | 34 | ### 2. 可视化并保存 图片 35 | 36 | ```python 37 | from keras.utils.vis_utils import plot_model 38 | 39 | plot_model(model,to_file='model_1.png',show_shapes=True) 40 | ``` 41 | 42 | * 得到下面的结构图 43 | 44 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/wfvz8.jpg) 45 | 46 | 47 | 48 | ------ 49 | 50 | ### 3. 附注 51 | 52 | * 只需要简单看一下结构,和参数 53 | 54 | ```python 55 | model.summary() 56 | ``` 57 | 58 | * 得到下面的图 59 | 60 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/vhbfv.jpg) 61 | 62 | ----- 63 | 64 | 65 | 66 | 67 | 68 | ### 参考 69 | 70 | 71 | https://github.com/XifengGuo/CapsNet-Keras/issues/7 72 | 73 | https://www.jianshu.com/p/275aad639b5e 74 | 75 | https://www.jianshu.com/p/3a97c0a43beb -------------------------------------------------------------------------------- /Machine_Learning/keras中模型的保存和重新导入.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/oy721.jpg) 2 | 3 | ---- 4 | 5 | ### 1. 保存 神经网络模型 到JSON 6 | > JSON 文件能够分层级的描述数据 7 | 8 | 保存模型 使用 to_json 函数,将模型转换成 json 格式,之后就可以保存模型到文件 9 | 10 | ```python 11 | model_json = model.to_json() 12 | with open("model.json", "w") as json_file: 13 | json_file.write(model_json) 14 | ``` 15 | 16 | 保存 参数 17 | 18 | ```python 19 | model.save_weights("model.h5") 20 | ``` 21 | 22 | 23 | 重新创建一个新的模型并导入 24 | 25 | ```python 26 | json_file = open('model.json', 'r') 27 | loaded_model_json = json_file.read() 28 | json_file.close() 29 | loaded_model = model_from_json(loaded_model_json) 30 | 31 | ``` 32 | 33 | 34 | 将权重导入到新建的模型里面 35 | 36 | ```python 37 | loaded_model.load_weights("model.h5") 38 | ``` 39 | 40 | JSON 保存的模型格式 41 | 42 | ```json 43 | 44 | "keras_version":"2.0.2", 45 | "backend":"theano", 46 | "config":[ 47 | { 48 | "config":{ 49 | "dtype":"float32", 50 | "bias_regularizer":null, 51 | "activation":"relu", 52 | "bias_constraint":null, 53 | "use_bias":true, 54 | "bias_initializer":{ 55 | "config":{ 56 | 57 | }, 58 | "class_name":"Zeros" 59 | }, 60 | "kernel_regularizer":null, 61 | "activity_regularizer":null, 62 | "kernel_constraint":null, 63 | "trainable":true, 64 | "name":"dense_1", 65 | "kernel_initializer":{ 66 | "config":{ 67 | "maxval":0.05, 68 | "minval":-0.05, 69 | "seed":null 70 | }, 71 | "class_name":"RandomUniform" 72 | }, 73 | "batch_input_shape":[ 74 | null, 75 | 8 76 | ], 77 | "units":12 78 | }, 79 | "class_name":"Dense" 80 | }, 81 | { 82 | "config":{ 83 | "kernel_regularizer":null, 84 | "bias_regularizer":null, 85 | "activation":"relu", 86 | "bias_constraint":null, 87 | "use_bias":true, 88 | "bias_initializer":{ 89 | "config":{ 90 | 91 | }, 92 | "class_name":"Zeros" 93 | }, 94 | "activity_regularizer":null, 95 | "kernel_constraint":null, 96 | "trainable":true, 97 | "name":"dense_2", 98 | "kernel_initializer":{ 99 | "config":{ 100 | "maxval":0.05, 101 | "minval":-0.05, 102 | "seed":null 103 | }, 104 | "class_name":"RandomUniform" 105 | }, 106 | "units":8 107 | }, 108 | "class_name":"Dense" 109 | }, 110 | { 111 | "config":{ 112 | "kernel_regularizer":null, 113 | "bias_regularizer":null, 114 | "activation":"sigmoid", 115 | "bias_constraint":null, 116 | "use_bias":true, 117 | "bias_initializer":{ 118 | "config":{ 119 | 120 | }, 121 | "class_name":"Zeros" 122 | }, 123 | "activity_regularizer":null, 124 | "kernel_constraint":null, 125 | "trainable":true, 126 | "name":"dense_3", 127 | "kernel_initializer":{ 128 | "config":{ 129 | "maxval":0.05, 130 | "minval":-0.05, 131 | "seed":null 132 | }, 133 | "class_name":"RandomUniform" 134 | }, 135 | "units":1 136 | }, 137 | "class_name":"Dense" 138 | } 139 | ], 140 | "class_name":"Sequential" 141 | ``` 142 | 143 | 144 | --- 145 | 146 | 147 | ### 2. 保存模型到 YAML 148 | 149 | 完全类似于 JSON -- 不详述 150 | 151 | ---- 152 | 153 | 154 | 155 | 156 | # 参考 157 | 158 | https://machinelearningmastery.com/save-load-keras-deep-learning-models/ -------------------------------------------------------------------------------- /Machine_Learning/使用 LSTM 预测时间序列数据时候的陷阱.md: -------------------------------------------------------------------------------- 1 | 2 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/k361e.jpg) 3 | 4 | --- 5 | 6 | **原文link** --- https://towardsdatascience.com/how-not-to-use-machine-learning-for-time-series-forecasting-avoiding-the-pitfalls-19f9d7adf424 7 | 8 | ---- 9 | 10 | 11 | ### 1. 时间序列预测的机器学习模型 12 | 13 | LSTM : 一种特殊的神经网络,通过之前的数据来进行预测 14 | 然而, 通常好像更简单的模型例如:随机森林,gradient boosting regressor , 时间延迟神经网络等等 15 | 16 | ### 2. 例子: 时间序列数据预测 17 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/dlmrk.jpg) 18 | 19 | 观察上图,预测结果和真实的结果很接近,具有较好的准确性。 20 | 21 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/6p5q5.jpg) 22 | 23 | 为了更准确一点, 我们可以通过plot 预测的 和实际的 数值来评估模型的精确度。 24 | 25 | 26 | 27 | ---- 28 | 29 | ### 3. 可能这个模型是错的 30 | 31 | 32 | 在本例中,为了便于说明,显式地选择了数据来表示实际上无法预测的数据。更具体地说,我称之为“股票指数”的数据实际上是用随机游走过程建模的 33 | 顾名思义,随机游走是一个完全随机的过程。因此,使用历史数据作为训练集来学习行为和预测未来结果的想法是不可能的。既然如此,那么这个模型怎么可能给出如此准确的预测呢?随着我将更详细地讨论,这一切都归结于对精度度量的(错误)选择。 34 | 35 | 36 | ### 4. 时间延迟预测 和自相关 37 | 38 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ynx5n.jpg) 39 | 40 | 41 | 时间序列数据具有时间相关性,且具有显著的自相关性。在这种情况下,这意味着时间t+1的值很可能接近时间t的值。正如上图所示,模型实际所做的是,在预测“t+1”时刻的值时,它只是使用“t”时刻的值作为预测(通常称为持久性模型)。通过绘制预测值与实际值之间的相互关系(下图),我们可以看到在1天的滞后时间内出现了一个清晰的峰值,这表明模型只是使用之前的值作为对未来的预测 42 | 43 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/8vwzn.jpg) 44 | 45 | 46 | ### 5. 时间序列数据的平稳性 47 | 48 | 平稳时间序列是指其统计特性,如均值、方差、自相关等,在一段时间内都是恒定的。大多数统计预测方法都是基于时间序列可以近似平稳的假设(即(“固定的”)通过数学变换的使用。一个这样的基本转换,对数据进行时间差分,如下图所示。 49 | 50 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/bfln1.jpg) 51 | 52 | 53 | 54 | ### 6. 时间差分数据 的预测模型 55 | 56 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/1svai.jpg) 57 | 58 | 预测时间差分数据,而不是直接预测数据,模型的预测能力更强 59 | 60 | 图片显示,模型不能够基于历史事件来预测未来的变化,这是我们想要看到的结果,因为我们使用的数据是来自统计的随机行走过程,这个过程未来是几乎不可预测的。 61 | 62 | 63 | 64 | 65 | ### 7. 时间序列是否是一个随机游走过程 66 | 67 | 68 | * 时间序列具有很强的时间相关性(自相关),线性衰减或以类似的模式衰减。 69 | 70 | * 时间序列是非平稳的,使其平稳在数据中没有明显的可学习结构。 71 | 72 | * 持久性模型(将上一个时间步骤的观察结果作为下一个时间步骤的观察结果)提供了可靠预测的最佳来源 73 | 74 | 使用持久性模型的基线预测可以快速表明您是否可以做得更好。如果你不能,你可能正在处理一个随机游走(或接近它) 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Machine_Learning/单元线性回归.md: -------------------------------------------------------------------------------- 1 | * 原项目 link --https://github.com/Avik-Jain/100-Days-Of-ML-Code/blob/master/Code/Day2_Simple_Linear_Regression.md 2 | 3 | **本文是对原文的额一个汉化,以及相应的内容补充** 4 | 5 | * GitHub 项目链接 ---https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day2_SImple_Linear_regression/README.md 6 | ----- 7 | 8 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/qdrex.jpg) 9 | 10 | ---- 11 | 12 | 13 | ## 1. goal 14 | 15 | ### 1 使用单一特征 预测 结果(response) 16 | * 假定两个变量线性相关,尝试寻找一个线性方程 来进行尽可能精确的预测 17 | 18 | ### 2寻找最好的拟合直线 19 | * 最小化 实际观测值$y_{i}$和预测值$y_{p}$之间的长度 20 | $$min{sum(y_{i}-y_{p})^{2}}$$ 21 | 22 | ### 3 回归任务 23 | 预测学生的 分数(百分制) 与他们学习时间之间的关系 24 | $$score = b_{0} + b_{1}* hours$$ 25 | 26 | 27 | 28 | ## 2. 实操 29 | 30 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0do4j.jpg) 31 | ### Step 1: 预处理数据-----类似于[Day1](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day1_Data_preprocessing/README.md) 32 | 1. 导入库 33 | 2. 导入数据集 34 | 3. 检查缺失数据 35 | 4. 分割数据集 36 | 5. 特征缩放-----使用专有的库 37 | 38 | ```python 39 | import pandas as pd 40 | import numpy as np 41 | import matplotlib.pyplot as plt 42 | 43 | dataset = pd.read_csv('studentscores.csv') 44 | X = dataset.iloc[ : , : 1 ].values 45 | Y = dataset.iloc[ : , 1 ].values 46 | 47 | from sklearn.cross_validation import train_test_split 48 | X_train, X_test, Y_train, Y_test = train_test_split( X, Y, test_size = 1/4, random_state = 0) 49 | 50 | 51 | ``` 52 | 53 | ### Step 2: Fitting Simple Linear Regression Model to the training set 54 | * 把数据集 拟合到简单线性回归模型 使用fit函数 55 | ```python 56 | from sklearn.linear_model import LinearRegression 57 | regressor = LinearRegression() ## 创建一个regressor 对象 58 | regressor = regressor.fit(X_train, Y_train) ### 对象拟合到数据集里面 59 | ``` 60 | 61 | ### Step 3: Predecting the Result 62 | * 在训练好的regressor使用预测模型 63 | * 结果输出到向量Y_pred 64 | 65 | ```python 66 | Y_pred = regressor.predict(X_test) 67 | ``` 68 | 69 | 70 | ### Step 4: Visualization 71 | ```python 72 | plt.scatter(X_train , Y_train, color = 'red') 73 | plt.plot(X_train , regressor.predict(X_train), color ='blue') ## 训练结果 74 | plt.scatter(X_test , Y_test, color = 'green') 75 | plt.plot(X_test , regressor.predict(X_test), color ='blue') ## 测试结果 76 | ``` 77 | **ps: 结果可视化中 测试集的结果使用Y_test因为y_pred上的点和预测曲线高度重合** 78 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/yn63n.jpg) 79 | ## 3.结果 80 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/imvga.jpg) 81 | 82 | ### [1 所需数据集](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day2_SImple_Linear_regression/studentscores.csv) 83 | ### [2 完整代码](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day2_SImple_Linear_regression/Simple_linear_regression.py) 84 | 85 | 86 | # 小问题 87 | 88 | ## 1 数学公式显示 89 | 安装 chrome中的 [Google with mathjax](https://chrome.google.com/webstore/detail/github-with-mathjax/ioemnmodlmafdkllaclgeombjnmnbima/related) 插件 90 | 91 | 92 | # 参考 93 | 1. https://chrome.google.com/webstore/detail/github-with-mathjax/ioemnmodlmafdkllaclgeombjnmnbima/related 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Machine_Learning/多元线性回归.md: -------------------------------------------------------------------------------- 1 | **本文是对原文的额一个汉化,以及相应的内容补充** 2 | 3 | * GitHub 项目链接 ---https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day3_Multiple_Linear_regression/Multiple_Linear_regression.py 4 | ----- 5 | 6 | 7 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/tlbgc.jpg) 8 | 9 | ---- 10 | 11 | 12 | ## 1 分析 13 | ### 1 多元线性回归 14 | * 使用模型(根据观测到的值拟合的线性方程)描述一个结果和两个或者两个以上的特征之间的关系 15 | * 实现过程类似于 单特征值 16 | * 通过分析,找出对预测结果影响最大的特征,以及不同变量之间的相关性。 17 | $$y = b_{0} + b_{1}x_{1} + b_{2}x_{2} +...+b_{n}x_{n}$$ 18 | 19 | ### 2 预测 20 | * 一个成功的回归分析,必须证明下面预测正确 21 | 22 | 1. 线性性:变量和自变量之间是线性关系。 23 | 2. 同方差性:总体回归函数中的随机误差项(干扰项)在解释变量条件下具有不变的方差。 24 | 3. 多元正态性 :多因素共同影响结果 25 | 4. 没有多重共线性: 自变量间相互关系较弱,或几乎没有。-----例如 虚拟变量陷阱 26 | 27 | ### 3 筛选变量 28 | * 变量过多 导致模型不精确 29 | * 变量对结果无作用 却对其他自变量有很大的作用 30 | 31 | 1.forward selection:一个个加入feature 32 | > 1)选择一个差异等级(significance level)比如SL=0.05 意味着对结果有95%贡献 (2)建立所有的简单回归的模型,并找到最小的P值 (3)确立一个简单模型,并将拥有最小P值的变量加入此模型 (4)如果P>SL,模型建立成功,否则在进行第三步 33 | 34 | 2.Backward Elimination:首先包含了所有的feature,然后每个feature都尝试去删除,测试删除的哪个feature对模型准确性有最大的提升,最终删掉对模型提升最高的一个特征。如此类推,直到删除feature并不能提升模型为止。 35 | 36 | 3.Stepwise则是结合上述两者的方法,当一个feature新加入后,stepwise会尝试删去一个feature,直至达到某个预设的标准。这种方法的缺点是,预设的标准不好定,而且容易陷入到过拟合当中-----https://onlinecourses.science.psu.edu/stat501/node/329/ 37 | 38 | 4.Bi-direction Comparision 39 | 40 | 41 | ### 4 虚拟变量 42 | * 使用分类数据 将非数字数据加入模型 43 | 44 | ### 5 虚拟变量陷阱 45 | * 如果模型中每个定性因素有m个相互排斥的类型, 且模型有截距项,则模型中只能引入m-1个虚拟变量, 否则会出现完全多重共线性 46 | > 拿性别来说,其实一个虚拟变量就够了,比如 1 的时候是“男”, 0 的时候是”非男”,即为女。如果设置两个虚拟变量“男”和“女”,语义上来说没有问题,可以理解,但是在回归预测中会多出一个变量,多出的这个变量将会对回归预测结果产生影响。一般来说,如果虚拟变量要比实际变量的种类少一个。 47 | 48 | ## 2 实操 49 | 50 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ymcj6.jpg) 51 | 52 | ### Step1 数据预处理----类似于 [Day1_Data preprocessing](https://github.com/LiuChuang0059/100days-ML-code/tree/master/Day1_Data_preprocessing) 53 | **但是要注意 避开虚拟变量陷阱** 54 | 55 | ```python 56 | import pandas as pd 57 | import numpy as np 58 | import matplotlib.pyplot as plt 59 | 60 | dataset = pd.read_csv('50_Startups.csv') 61 | X = dataset.iloc[ : , :-1].values 62 | Y = dataset.iloc[ : , 4 ].values 63 | 64 | from sklearn.preprocessing import LabelEncoder, OneHotEncoder 65 | labelencoder = LabelEncoder() 66 | X[: , 3] = labelencoder.fit_transform(X[ : , 3]) 67 | onehotencoder = OneHotEncoder(categorical_features = [3]) 68 | X = onehotencoder.fit_transform(X).toarray() 69 | 70 | X = X[: , 1:] ### 避免虚拟变量陷阱 71 | 72 | from sklearn.cross_validation import train_test_split ## 分割数据集 73 | X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2, random_state = 0) 74 | ``` 75 | 76 | PS: 避免虚拟数据陷阱,只选择 两个(3-1)虚拟变量 77 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ee4yk.jpg) 78 | 79 | ### Step 2: Fitting Multiple Linear Regression to the Training set----类似于[Day2-简单线性回归](https://github.com/LiuChuang0059/100days-ML-code/tree/master/Day2_SImple_Linear_regression) 80 | 81 | ```python 82 | from sklearn.linear_model import LinearRegression 83 | regressor = LinearRegression() 84 | regressor.fit(X_train, Y_train) ## 多重线性回归模型应用到训练集 85 | ``` 86 | 87 | ### Step 3: Predicting the Test set results 88 | 89 | ```python 90 | y_pred = regressor.predict(X_test) 91 | 92 | ``` 93 | 94 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/kpdzp.jpg) 95 | 96 | ### Step 4: 可视化 97 | ```python 98 | plt.scatter(np.arange(10),Y_test, color = 'red',label='y_test') 99 | plt.scatter(np.arange(10),y_pred, color = 'blue',label='y_pred') 100 | plt.legend(loc=2); 101 | plt.show() 102 | ``` 103 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0co5x.jpg) 104 | 105 | 106 | ## 3 107 | ### 1 [完整代码](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day3_Multiple_Linear_regression/Multiple_Linear_regression.py) 108 | ### 2 [所需数据](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day3_Multiple_Linear_regression/50_Startups.csv) 109 | 110 | 111 | 112 | 113 | # 参考 114 | 115 | 1. 筛选变量 : https://blog.csdn.net/joeland209/article/details/69362422 116 | 2. 虚拟变量 : https://www.moresteam.com/whitepapers/download/dummy-variables.pdf 117 | 3. 虚拟变量陷阱 : https://www.jianshu.com/p/b2e018007dc3 118 | 4. 逐步回归 : https://onlinecourses.science.psu.edu/stat501/node/329/ 119 | -------------------------------------------------------------------------------- /Machine_Learning/数据处理 5 种采样方法.md: -------------------------------------------------------------------------------- 1 | 原文: The 5 Sampling Algorithms every Data Scientist need to know 2 | 3 | link : https://towardsdatascience.com/the-5-sampling-algorithms-every-data-scientist-need-to-know-43c7bc11d17c 4 | 5 | ---- 6 | 7 | 8 | 9 | ## 0. 数据集 10 | 11 | | - | User ID | Gender | Age | EstimatedSalary | Purchased | 12 | |:-:|:--------:|:------:|:---:|:---------------:|:---------:| 13 | | 0 | 15624510 | Male | 19 | 19000 | 0 | 14 | | 1 | 15810944 | Male | 35 | 20000 | 0 | 15 | | 2 | 15668575 | Female | 26 | 43000 | 0 | 16 | | 3 | 15603246 | Female | 27 | 57000 | 0 | 17 | | 4 | 15804002 | Male | 19 | 76000 | 0 | 18 | 19 | 20 | ## 1. 简单随机采样 21 | 22 | 选择一个总体的子集,其中子集的每个成员被选中的概率相等。 23 | 24 | ```python 25 | import numpy as np 26 | import matplotlib.pyplot as plt 27 | import pandas as pd 28 | 29 | data = pd.read_csv("Social_Network_Ads.csv") 30 | data_2 = data.copy() 31 | 32 | sample_data = data_2.sample(frac=0.2) 33 | sample_data.head() 34 | ``` 35 | 36 | | - | User ID | Gender | Age | EstimatedSalary | Purchased | 37 | |:---:|:--------:|:------:|:---:|:---------------:|:---------:| 38 | | 194 | 15689751 | Male | 28 | 89000 | 0 | 39 | | 123 | 15574305 | Male | 35 | 53000 | 0 | 40 | | 344 | 15729908 | Male | 47 | 105000 | 1 | 41 | | 167 | 15614827 | Female | 35 | 71000 | 0 | 42 | | 31 | 15729054 | Female | 27 | 137000 | 1 | 43 | 44 | 45 | ----- 46 | 47 | ## 2. 分层抽样 48 | 49 | 例如我们进行选举投票时候, 每个城市的投票人假设随机抽取。 A 城 100K 人,B 城 200K 人, C城 300K 人, 抽取人的时候,就要按照相应额度比例抽取。 50 | 51 | 对我们的数据集, 随机抽取没有考虑 男女的比率。 52 | 53 | ```python 54 | y = data_2['Purchased'] 55 | X = data_2.drop(columns= ['User ID', 'Purchased']) 56 | 57 | X_train, X_test, y_train, y_test = train_test_split(X, y, 58 | stratify=X['Gender'], 59 | test_size=0.25) 60 | ``` 61 | 62 | 63 | --- 64 | 65 | ## 3. Reservoir Sampling 水库抽样 66 | 67 | 假如有一个数据流,不知道大小,只能不停的迭代获取下一个, 希望能够在数据流中随机选取一个数据 , 每个数据被选中的概率大致相同。 68 | 69 | 70 | ```python 71 | import random 72 | 73 | # 创建数据流 74 | def generator(max): 75 | number = 1 76 | while number < max: 77 | number += 1 78 | yield number 79 | 80 | stream = generator(10000) 81 | 82 | # 水库抽样 83 | 84 | k = 5 85 | reservoir = [] 86 | 87 | for number , element in enmurate(stream): 88 | if number +1 < k: 89 | reservoir.append(element) 90 | else: 91 | probability = k/(number + 1) 92 | if probability > random.random(): 93 | reservoir[random.choice(range(0,k))] = element 94 | 95 | print(reservoir) 96 | 97 | ###### Output ##### 98 | 99 | [3386, 565, 2734, 5278, 6457] 100 | 101 | ``` 102 | 103 | 简单数学证明 : 104 | 105 | 假设我们无限数据流只有 3 个数据 [a, b, c], 我们选择两个数据。 106 | a, b 因为列表有位置直接加入到 list , c 选入的概率是 k/(number) = 2/3 107 | 108 | a 被选出来的概率是 : ( c被选中 * a,b 中选一个被选出去)2/3 * 1/2= 1/3 109 | 110 | a 选入数据集的概率: 1-1/3 = 2/3 = k/n 111 | 112 | 113 | 114 | ----- 115 | 116 | ## 4. Random Undersampling and Oversampling 随机过采样和欠采样 117 | 118 | 119 | ![](https://i.loli.net/2019/08/28/FPaz8LUNXDW5Ktc.png) 120 | 121 | 122 | 对于不平衡数据集,常用的技巧是进行重采样 : 123 | * 从大的数据类中 抽取一部分数据: Undersampling 124 | 125 | * 向小的数据中添加数据 126 | 127 | 128 | ```python 129 | from sklearn.datasets import make_classification 130 | 131 | # 创建一个二分类不平衡数据集 : 9: 1 132 | X, y = make_classification( 133 | n_classes=2, class_sep=1.5, weights=[0.9, 0.1], 134 | n_informative=3, n_redundant=1, flip_y=0, 135 | n_features=20, n_clusters_per_class=1, 136 | n_samples=100, random_state=10 137 | ) 138 | X = pd.DataFrame(X) 139 | X['target'] = y 140 | 141 | 142 | 143 | # 查看两类的数据分别有多少 144 | num_0 = len(X[X['target']==0]) 145 | num_1 = len(X[X['target']==1]) 146 | print(num_0,num_1) 147 | 148 | # random undersample 149 | undersampled_data = pd.concat([ X[X['target']==0].sample(num_1) , X[X['target']==1] ]) 150 | print(len(undersampled_data)) 151 | # random oversample 152 | oversampled_data = pd.concat([ X[X['target']==0] , X[X['target']==1].sample(num_0, replace=True) ]) 153 | print(len(oversampled_data)) 154 | 155 | ##### Output ##### 156 | 90 10 157 | 20 158 | 180 159 | 160 | ``` 161 | 162 | 163 | 164 | ------ 165 | 166 | 167 | ## 5. 使用 imbalanced-learn(imblearn) 库 处理不平衡数据 168 | 169 | 1. 使用 tomek link 进行 欠采样 170 | 171 | Tomek Links : 选取相近的对立类的数据 172 | 173 | ![](https://i.loli.net/2019/08/28/MEKmOpIi4qAslkR.png) 174 | 175 | 176 | ```python 177 | from imblearn.under_sampling import TomekLinks 178 | 179 | tl = TomekLinks(return_indices=True, ratio='majority') 180 | X_tl, y_tl, id_tl = tl.fit_sample(X, y) 181 | ``` 182 | 183 | 184 | 185 | 2. SMOTE Synthetic Minority Oversampling Technique 进行 过采样 186 | 187 | 在少数类数据旁边为少数类合成元素 188 | 189 | ![](https://i.loli.net/2019/08/28/rZWUzM8wmP2NdEA.png) 190 | 191 | ```python 192 | from imblearn.over_sampling import SMOTE 193 | 194 | smote = SMOTE(ratio='minority') 195 | X_sm, y_sm = smote.fit_sample(X, y) 196 | ``` 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /Machine_Learning/时间序列数据分析步骤.md: -------------------------------------------------------------------------------- 1 | 原文 :Time Series Analysis Tutorial Using Financial Data 2 | 3 | link : https://towardsdatascience.com/time-series-analysis-tutorial-using-financial-data-4d1b846489f9 4 | 5 | 6 | 完整代码 link : https://github.com/NathanMaton/vix_prediction/blob/master/README.md 7 | 8 | 9 | ----- 10 | 11 | 12 | ## 1. 探索数据 13 | 14 | 绘制数据 : 15 | 16 | ![](https://i.loli.net/2019/08/05/oC51iTO7twXDBJU.png) 17 | 18 | * 在金融危机的时候,有一个大的凹陷 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ## 2. 检查平稳性 27 | 28 | 一个平稳的时间序列他的统计特性例如: 平均值,方差, 自相关系数等都是随着时间变化恒定不变的。 29 | 大多数统计 forecasting 方法都是基于数据在经过数学变换之后近乎稳定的假设。 30 | 31 | 稳定的序列相对来说是容易去预测的, 因为我们可以假定 未来数据的统计特性和过去的统计特性是一样的。 32 | 因此,如何将序列转换为稳定序列通常至关重要。再者, 将序列稳定化之后,更有可能获得一些有意义的统计量,例如: 平均值,方差, 和其他变量之间的关联性。 33 | 34 | 但是大多数商业和金融时间序列数据远不是平稳数据,即使经过一系列的处理, 还是存在 趋势,循环,随机游走, 以及其他的非统计表现。 35 | 36 | 对于数据,需要确保不是从头到尾都有一个整体的趋势, 一些 每天的每周的每月的趋势是可以的,模型可以利用这些缺失做更好的预测 37 | 38 | ![](https://i.loli.net/2019/08/05/TRrSd1yfVpqQG6v.png) 39 | 40 | * p-value: 小于 0.05, 判断我们的模型是不是稳定的, 小于 0.05 数据稳定,可以建模 41 | 42 | 43 | ## 3. 建立模型,以及模型优化 44 | 45 | 使用 ARIMA, SARIMA 等模型 : (来自 StatsModels 库) 46 | 47 | 绘制 自相关和 偏自相关图 48 | 49 | ![](https://i.loli.net/2019/08/05/kh7Tn5qBg2NEmRF.png) 50 | 51 | * 相关性迅速跌落 52 | 53 | * 自相关图和 偏自相关图基本接近 54 | > 偏自相关图展现的是 和之前某几个数据的直接关联性, 不考虑中间数据传递的影响 55 | 56 | * 蓝色区域是置信区间, 落在置信区间的数据说明不太值得加入到模型中 57 | 58 | 59 | ## 4. 60 | 61 | 分别调用 ARIMA, SARIMA 等模型 62 | 63 | **使用一种方法 :** 64 | 65 | ![](https://i.loli.net/2019/08/05/XFeYnuzpWoj6l5h.png) 66 | 67 | 如果要预测 10个 输出点, 不直接一次性预测 10个 输出点, 而是利用已有数据预测一个, 之后将预测值加入到已有值序列,再预测下一个值。 68 | 69 | > 会积累误差 70 | 71 | 72 | 类似于 Seq2Seq 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | # 参考 83 | 84 | 1. Stationarity and differencing : https://people.duke.edu/~rnau/411diff.htm -------------------------------------------------------------------------------- /Machine_Learning/时间序列预测中的 Baseline predictions.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/65pl7.jpg) 2 | 3 | --- 4 | 5 | 6 | **原文 link** --- https://machinelearningmastery.com/persistence-time-series-forecasting-with-python/ 7 | 8 | ---- 9 | 10 | 11 | 12 | ### 1. 预测效果的 Baseline 13 | 14 | 这个 baseline 是一个参考点,如果其他的模型表现效果不如或者和 baseline 差不多,那么模型需要被修正或者丢弃。 15 | 16 | 在进行建立基线模型前,需要准备好 数据集,采样方法,效果评估方法(MSE)。之后选择一个简单的原始的方法进行建模预测,并且计算baseline 的表现,便于自己理解数据集,更好的开发新的模型。 17 | 18 | 适合 baseline 预测方法的 三个特性: 19 | 20 | * 简单 21 | 22 | * 快速 23 | 24 | * 可重复性: 给定同样的输入,得到相同的输出 25 | 26 | **用于建立 baseline的算法 称为 persistence algorithm** 27 | 28 | --- 29 | 30 | 31 | 32 | ### 2. Persistence Algorithm 33 | 34 | 对于监督学习最常用的 baseline 方法就是 Zero Rule 算法 --简单的说就是根据问题自定义合适的函数 35 | > 参考 https://machinelearningmastery.com/implement-baseline-machine-learning-algorithms-scratch-python/ 36 | 37 | 38 | 1. 数据准备 39 | 40 | ``` 41 | t-1 t+1 42 | 0 NaN 266.0 43 | 1 266.0 145.9 44 | 2 145.9 183.1 45 | 3 183.1 119.3 46 | 4 119.3 180.3 47 | 48 | ``` 49 | 50 | 2. 定义 persistence 模型 为一个函数 : 返回输入值的函数 51 | 52 | ```python 53 | # persistence model 54 | def model_persistence(x): 55 | return x 56 | 57 | ``` 58 | 59 | 3. 之后不需要模型训练,直接进行预测 计算 MSE( Mean Squared Error) 60 | 61 | ```python 62 | # walk-forward validation 63 | predictions = list() 64 | for x in test_X: 65 | yhat = model_persistence(x) 66 | predictions.append(yhat) 67 | test_score = mean_squared_error(test_y, predictions) 68 | print('Test MSE: %.3f' % test_score) 69 | ``` 70 | 71 | 4. plot persistence 模型预测的结果(就是我们定义的返回输入值(t-1时刻值)的函数);可以看到就是我们设计的 推后一天 72 | 73 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/dgw05.jpg) 74 | 75 | 76 | ----- 77 | 78 | 79 | 80 | ### 3. why 81 | 82 | persistence 模型是 naive的 ,通常也被叫做 naive forecast 83 | 84 | 他没有利用到 他处理的时间数据的细节,所以很容易快速的实现。 85 | 86 | **This is useful because these ideas can become input features in a feature engineering effort or simple models that may be combined in an ensembling effort later.** 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Machine_Learning/机器学习中的随机性.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/zz341.jpg) 2 | 3 | ----- 4 | 5 | 6 | ### 1. 机器学习算法中的 随机性 7 | 8 | #### 1. 数据收集中的随机性 9 | 10 | 不同的数据,机器学习算法会构建不同的模型 , 数据本身就是一种随机性 11 | 12 | #### 2. 数据输入顺序 (Observation Order) 13 | 14 | 数据输入到模型的顺序会影响内部的决策。一些算法(神经网络)尤其明显敏感。在每次训练迭代之前打乱训练数据的顺序是一个比较好的方法。 15 | 16 | #### 3. 算法的随机性 17 | 18 | 算法会初始化到一个随机的状态:例如神经网络中的初始化权重 19 | > Votes that end in a draw (and other internal decisions) during training in a deterministic method may rely on randomness to resolve. 20 | 21 | 22 | 23 | #### 4. 采样的随机性 24 | 训练数据太多,需要随机的采集子样本 25 | 26 | #### 5. 重采样的随机性 -- resampling 27 | 28 | 当我们测试一个算法,使用随机分割(train/test)数据集或者 k-fold 交叉验证的方法随机 k 份分割 29 | 30 | 31 | ---- 32 | 33 | ### 2. Random Seeds and Reproducible Results -- 随机种子和可重复结果 34 | 35 | 36 | 我们通过使用完全相同的 code data 和 **随机数序列** 实现可重复性。随机数通过内部的随机数生成器生成,是由一个简单的函数生成一系列的数字,这个函数是**固定的** 37 | 38 | 随机数的生成函数固定,如果使用同样的其实点-- **seed number**,就会生成相同的随机数字。 39 | 40 | 所以,我们可以获得可重复性结果通过固定 **生成器的种子** 41 | 42 | ---- 43 | 44 | ### 3. 解决算法不确定性的策略 45 | 46 | #### 1. 减少不确定性 47 | 随机重复和随机再重启 --andom repeats or random restarts. 48 | 49 | 尝试多次 run 这个模型 gather a population of performance measures 50 | 51 | 类似于 k-fold 建立多个模型,只要数据还能代表问题。 52 | 53 | 或者重复评估过程 n 次 54 | 55 | #### 2. 报告不确定性 56 | > Never report the performance of your machine learning algorithm with a single number. 57 | 58 | 59 | 已经有 a population of performance measures, 根据统计学,结果应该呈现高斯分布的 60 | 61 | 最好报告一个表现的 **平均值和标准差**以及 最好和最坏的数据 62 | 63 | 64 | --- 65 | 66 | ### 4. final model 的选择 67 | 68 | 使用不同的 随机数序列能够有不同的模型,那我们应该选择一个在 validation 中表现最好的模型吗(精度最高)? 69 | 70 | > validation set 完全独立, 71 | 72 | **不应该**, 因为这高度依赖 validation 数据集的数据质量,不能因为一小部分数据来优化这个随机数 73 | 74 | 75 | > Sometimes your application domain makes you care more. 76 | In this situation, I would tell you to build an ensemble of models, each trained with a different random number seed. 77 | Use a simple voting ensemble. Each model makes a prediction and the mean of all predictions is reported as the final prediction. 78 | Make the ensemble as big as you need to. I think 10, 30 or 100 are nice round numbers. 79 | Maybe keep adding new models until the predictions become stable. For example, continue until the variance of the predictions tightens up on some holdout set. 80 | 81 | 82 | 83 | 84 | 85 | # 参考 86 | 87 | https://machinelearningmastery.com/randomness-in-machine-learning/ 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Machine_Learning/机器学习数据预处理.md: -------------------------------------------------------------------------------- 1 | * 原项目 link ---https://github.com/Avik-Jain/100-Days-Of-ML-Code/blob/master/Code/Day%201_Data%20PreProcessing.md 2 | **本文是对原文的额一个汉化,以及相应的内容补充** 3 | 4 | * GitHub 项目链接 ---https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day1_Data_preprocessing/README.md 5 | ----- 6 | 7 | 8 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/7xj39.jpg) 9 | 10 | 11 | 12 | ## Step 1: Importing the libraries 13 | * [numpy]() : 包含 数学函数 14 | * [pandas](): 导入和管理 数据集 15 | 16 | ```python 17 | import numpy as np 18 | import pandas as pd 19 | ``` 20 | 21 | ## Step 2: Importing dataset 22 | 23 | * 数据集通常在.csv 文件中 24 | * csv文件储存 表格式数据 25 | * 用 pandas 库里面的read_csv 读取本地csv文件 作为 [数据桢(dataframe)](http://wiki.jikexueyuan.com/project/start-learning-python/311.html) 26 | * 从数据帧中创建独立的矩阵和独立变量和因变量 27 | 28 | ```python 29 | dataset = pd.read_csv('Data.csv') 30 | X = dataset.iloc[ : , :-1].values ## 创建独立变量---选取前三列 31 | Y = dataset.iloc[ : , 3].values ## 创建依赖变量-----选取最后一列 返回值的类型仍为 dataframe 32 | ``` 33 | ps : [iloc 选取特定的列](https://blog.csdn.net/chenKFKevin/article/details/62049060) 34 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/xszvh.jpg) 35 | 36 | ## Step 3: Handling the missing data 37 | * 为了不影响机器学习模型效果,需要处理缺失的数据 38 | * 使用整列的中位数或者平均值表示缺失值 39 | * 使用[sklearn.preprocessing 中的 Imputer类](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html) 40 | 41 | ```python 42 | from sklearn.preprocessing import Imputer 43 | imputer = Imputer(missing_values = "NaN", strategy = "mean", axis = 0) 44 | imputer = imputer.fit(X[ : , 1:3]) 45 | X[ : , 1:3] = imputer.transform(X[ : , 1:3]) ## 将其应用到数据 46 | ``` 47 | 运行结果: 48 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/2ay1d.jpg) 49 | ## Step 4: Encoding categorical data 50 | * 分类数据:有标签值 而不是数字值---例如国家,性别 51 | * 分类数据具有有限的可能值 52 | * 编码这些变量 使得其具有 数字值 53 | * 需要sklearn.preprocessing 中的 LabelEncoder类, OneHotEncoder 54 | 55 | 因为不同国家的地位相同,不能设置1,2,3 而是将不同的类别(如不同国家)另外分为一个列,属于这个国家的设置为1,不属于的设置为0.: 56 | 57 | 58 | ```python 59 | from sklearn.preprocessing import LabelEncoder, OneHotEncoder 60 | labelencoder_X = LabelEncoder() 61 | X[ : , 0] = labelencoder_X.fit_transform(X[ : , 0]) 62 | 63 | onehotencoder = OneHotEncoder(categorical_features = [0]) 64 | X = onehotencoder.fit_transform(X).toarray() 65 | 66 | labelencoder_Y = LabelEncoder() //处理依赖变量 67 | Y = labelencoder_Y.fit_transform(Y) 68 | ``` 69 | 运行结果: 70 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/7ouak.jpg) 71 | 72 | 73 | ## Step 5: Splitting the datasets into training sets and Test sets 74 | 75 | * 数据集分成训练集和测试集 76 | * 分的比例通常 8:2 77 | * 使用sklearn.cross_validation 中 train_test_split 类 78 | 79 | ```python 80 | from sklearn.cross_validation import train_test_split 81 | X_train, X_test, Y_train, Y_test = train_test_split( X , Y , test_size = 0.2, random_state = 0) 82 | ``` 83 | ## Step 6: Feature Scaling---特征缩放 84 | * 使用欧几里得距离 85 | * 特征与 标度有关,一个特征比其他的特征范围更大 该特征值成为主导 86 | * 使用“特征标准化”-特征等同 87 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/a9zka.png) 88 | 89 | ```python 90 | from sklearn.preprocessing import StandardScaler 91 | sc_X = StandardScaler() 92 | X_train = sc_X.fit_transform(X_train) 93 | X_test = sc_X.fit_transform(X_test) 94 | 95 | ``` 96 | 97 | 98 | # 小问题: 99 | ## 1 pip安装sklearn 100 | > Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/sklearn' Consider using the `--user` option or check the permissions. 101 | Consider using the `--user` option or check the permissions. 102 | 103 | 解决: 尝试 104 | ``` 105 | sudo pip install sklearn 106 | ``` 107 | 108 | ## 2 run 代码的时候 出现小问题: 109 | 110 | > runfile('/Users/liuchuang/.spyder-py3/Data_preprocessing.py', wdir='/Users/liuchuang/.spyder-py3') 111 | /Users/liuchuang/anaconda3/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20. 112 | "This module will be removed in 0.20.", DeprecationWarning) 113 | 114 | * 解决:将 cross_validation 换成 model_selection 115 | 116 | 117 | 118 | # 参考 119 | 1. https://steveli90.github.io/2016/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E4%B8%80-%E5%85%A5%E9%97%A8 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Machine_Learning/深度学习进行信号处理和时间序列分析.md: -------------------------------------------------------------------------------- 1 | 2 | ## 1. 传统方法 3 | 在机器学习和深度学习之前, 人们通过创建数学模型进行时间序列和信号的分析。 4 | 5 | 6 | * 时域的分析 : 观察时间序列是如何随着时间进行演化。它可以包括分析宽度、时间步长、统计特征等看的见的特征。 7 | 8 | * 频域分析 : 某些信号在时域上不太好进行分析, 通过傅立叶变化和小波变换转换到频域分析其振幅的变化特性。 9 | 10 | * 近邻分析 : 有时我们只需要比较两个信号或者测量它们之间的距离,而我们不能用欧几里得这样的常规指标来做到这一点,因为信号可以有不同的长度,相似度的概念也有一点不同。 可以使用 DTW dynamic time warping. 11 | 12 | * (S)AR(I)MA(X) models : 一些基于自相关性的模型,对未来的波动有较好的解释 13 | 14 | * 拆分成分(组分): 将时间序列分解成可以求和或相乘的逻辑部分,从而得到初始时间序列. 例如 : 趋势部分、季节部分和残差。 15 | 16 | * 非线性动态 : 可以使用微分方程提取一些有用的信息 17 | 18 | 19 | 20 | --- 21 | 22 | 23 | ## 2. 深度学习 24 | 25 | ### 1. RNN 循环神经网络 26 | 27 | 为序列创造的网络, 能够学习到数据间的时间相关性,可以处理任意长度的序列。 但是在实际中,饿哦们很少直接使用,因为我们会遇到很多的问题。 28 | 29 | 根据作者的经验,只有当我们处理相当短的序列(10-100个时间步长),每个时间步长有多个变量(可以是多变量时间序列或单词嵌入)时,RNN 才是好的。在所有其他情况下,我们最好选择下一种: 30 | 31 | 32 | ### 2. 卷积神经网络 33 | 34 | 卷积神经网络擅长捕捉图片中 pattern ,甚至能够很好的处理三维图像数据。为什么我们不讲他应用到更加简单的一维数据中。 35 | 36 | 我们可以直接使用那些 state of art 的深度学习框架例如 ResNet 或者 DenseNet ,将其中的二维卷积更换为 1维。 37 | 它们表现出良好的性能,速度快,可以并行优化,在分类和回归方面都很好。对它们进行了多次基准测试,它们大多优于 RNNs。 38 | 39 | 40 | 41 | ### 3. CNN + RNN 42 | 43 | ![](https://i.loli.net/2019/08/29/AkjwsN8Ig1DeC4x.png) 44 | 45 | CNN 可以很好的捕捉局部 pattern, 但是我们可以假设这些 pattern 是有时间依赖性的。 46 | 47 | CNN 使用不同的池化技术可以对数据进行很好的降维处理, 降维后的数据(local pattern)可以使用循环神经网络, 检查这些 local pattern 之间的时间依赖性 48 | 49 | 50 | ### 4. 自回归神经网络 51 | 52 | 如果我们彻底不想使用循环神经网络, 有没有一种方法,模拟对过去 N个时间步的依赖,并且这个 N 可以十分的长。 53 | 54 | WaveNet 等结构的网络可以做到, 这个模型对 N 个 时间步使用 dilated convolutions. 55 | 56 | 57 | ![](https://i.loli.net/2019/08/29/SlEN53WLc2AZrH7.gif) 58 | 59 | 60 | ### 5. 聚类 61 | 62 | 除了 分类和回归问题,我们还对时间序列聚类感兴趣。 63 | 64 | 我们可以结合特定的时间序列距离(如上面提到的DTW)和基于度量的聚类算法(如K-Means)来实现这一点,但是这种方法非常慢,也不是最优的方法 65 | 66 | 我们想要一些可以处理不同长度的信号,但更有效的东西。当然,我们可以要求神经网络为我们提供一个嵌入空间,在那里我们将执行聚类,例如,自动编码器。然后我们可以在那个空间里聚类信号或者用辅助任务来增强自动编码器 67 | 68 | 69 | * [DEEP TEMPORAL CLUSTERING: FULLY UNSUPERVISED LEARNING OF TIME-DOMAIN FEATURES](https://arxiv.org/pdf/1802.01059.pdf) 70 | 71 | 72 | ### 6. 异常检测 73 | 74 | 通常,这个问题可以用一些阈值方法和距离来解决(有时是统计距离),但并不总是依赖于时间序列时间步长之间的欧氏距离。和以前的任务(集群)一样,我们可以依靠深度学习用自动编码器将数据嵌入到新的空间中,或者我们可以使用GANs(生成式对抗网络)作为异常检测器,使用discriminator网络作为异常检测器 75 | 76 | 77 | [GANs beyond generation: 7 alternative use cases](https://medium.com/@alexrachnog/gans-beyond-generation-7-alternative-use-cases-725c60ba95e8) 78 | 79 | 80 | [ae_anomaly.py](https://github.com/Rachnog/education/blob/master/anomaly/ae_anomaly.py?source=post_page-----725c60ba95e8----------------------) 81 | 82 | 83 | ### 7. 混合解决方法 84 | 85 | [Engineering Extreme Event Forecasting at Uber with Recurrent Neural Networks](https://eng.uber.com/neural-networks/) 86 | 87 | 88 | 89 | 90 | 91 | ## 3. 扩展阅读 92 | 93 | [Real-valued (Medical) Time Series Generation with Recurrent Conditional GANs](https://arxiv.org/abs/1706.02633) 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Machine_Learning/理解为什么 RNN 模型这么有效.md: -------------------------------------------------------------------------------- 1 | 2 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/870l5.jpg) 3 | 4 | ---- 5 | 6 | **原文link --- http://karpathy.github.io/2015/05/21/rnn-effectiveness/** 7 | 8 | --- 9 | 10 | ### 1. 字符语言模型 11 | 12 | > 给 RNN 模型一系列文本,要求 RNN模型学习 给定一个序列后,序列中下一个字符出现的概率。 13 | 14 | 假设给定一个训练的单词 “hello“ : 给定文本 “h”后很可能出现“e“; 给定 ”he" 或者“hel" 后很可能出现 “l”;给定文本"hell" 后 很可能出现 “o" 15 | 16 | 具体来说,使用 one-hot 给字符编码,一次输入 RNN 一个字符,得到 4 个输出 17 | 18 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/mssz8.jpg) 19 | 20 | 第一步输入 h 到 RNN , RNN 输出 4个 字符的可能性, 因为下一个字符是 “e”, 我们需要尽可能的提升 e 的数值(绿色的),降低其他数字的数值。 利用 **反向传播算法**实现参数更新--- 趋于我们想要的方向。再次输入会发现 e 的对应的数值会提升,其他的会降低。不断的重复这个过程,直到网络收敛,预测结果准确。 21 | > 每个输出向量上面使用 交叉熵损失, 使用 ADAM 更新优化 22 | 23 | **注意到**: 第一次输入 “l” 的目标 是 “l” 而第二次输入 “l” 的目标是“o”. 所以 RNN 模型不能仅仅依靠输入,还要使用 循环关系来追踪文本的上下文来实现这个任务 24 | 25 | 26 | --- 27 | 28 | 29 | ### 2. 模型有效的原因 30 | > code 暂缺,抽空补上 31 | 32 | #### 1. 多次训练过程中 模型的进化 33 | 34 | 训练一个 列夫托尔斯泰的 《战争与和平》,每循环100 次生成一次样本 35 | 36 | 100 次 --- 模型知道单词之间需要空格隔开 37 | ``` 38 | tyntd-iafhatawiaoihrdemot lytdws e ,tfti, astai f ogoh eoase rrranbyne 'nhthnee e 39 | plia tklrgd t o idoe ns,smtt h ne etie h,hregtrs nigtike,aoaenns lng 40 | ``` 41 | 42 | 300 次。--- 模型开始学会 引用和段落 43 | ``` 44 | "Tmont thithey" fomesscerliund 45 | Keushey. Thom here 46 | sheulke, anmerenith ol sivh I lalterthend Bleipile shuwy fil on aseterlome 47 | coaniogennc Phe lism thond hon at. MeiDimorotion in ther thize." 48 | ``` 49 | 50 | 500 次 --- 模型学会拼写简单的单词 we his 51 | ``` 52 | we counter. He stutn co des. His stanted out one ofler that concossions and was 53 | to gearang reay Jotrets and with fre colt otf paitt thin wall. Which das stimn 54 | ``` 55 | 56 | 1200 次 --- 使用长单词 和标点符号 57 | 58 | ``` 59 | "Kite vouch!" he repeated by her 60 | door. "But I would be done and quarts, feeling, then, son is people...." 61 | 62 | ``` 63 | 64 | 2000 次 --- 正确拼写的旦夕 引用 名字,标点等 65 | 66 | ``` 67 | "Why do what that day," replied Natasha, and wishing to himself the fact the 68 | princess, Princess Mary was easier, fed in had oftened him. 69 | Pierre aking his soul came to the packs and drove up his father-in-law women. 70 | 71 | ``` 72 | 73 | 74 | ---- 75 | 76 | #### 2. 预测结果可视化 77 | 78 | 每个输入字符(蓝色或者绿色)下面,都有 5个字符(模型预测出来的下一个最可能字符的 top5)颜色深浅对应可能性的大小。在一些字符下面,模型对预测非常的自信(例如: http:www.) 79 | 80 | 输入字符的颜色(蓝或者绿) 是基于 RNN 模型中隐藏状态中的 随机的一个神经元的激活性 上色的。 81 | 绿色= 非常活跃, 蓝色 = 很不活跃(对应于 LSTM cell state)。 82 | 83 | 例如下图,神经元好像对 URL 很兴奋,URL 之外的不是很兴奋,那么 LSTM 可能利用这个神经元来记忆是否在 URL 里面 84 | 85 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/jaqf7.jpg) 86 | 87 | 88 | 下面的图 神经元好像对 [[]] 里面的很兴奋,外面的不是很兴奋。而且**只有在看到第二个 [ 才会开始兴奋激活** 89 | 90 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/kxxyc.jpg) 91 | 92 | 93 | 下面的图,神经元突然在 第一个 w 之后关闭(不兴奋),RNN 可能利用这个神经元计算距离,知道是否应该给出下一个 w 或者给出 URL 94 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/t46pt.jpg) 95 | 96 | 97 | ---- 98 | 99 | #### 3. 只输出最可能的预测来可视化文本 100 | 101 | 1. 学习到了文本的额位置 102 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/gnphl.jpg) 103 | 104 | 2. 在引用里面很 excited turn on 105 | 106 | 107 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/z8ym3.jpg) 108 | 109 | 3. 在 if 态里面激活 110 | 111 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/qan65.jpg) 112 | 113 | 4. 对深度敏感 114 | 115 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/rrkls.jpg) 116 | 117 | 等等, 最重要的是, 我们不需要为这些功能编写代码(例如,记忆是否在引用里面这个功能)。我们只需要训练 LSTM。 118 | 而他的 cell 在训练过程中逐步调整成为相应的功能细胞(例如 引用检测),因为这样能帮助他更好的实现最终的任务 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /Machine_Learning/神经网络(RNN) 参数调节.md: -------------------------------------------------------------------------------- 1 | 2 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/rvxla.JPG) 3 | 4 | ---- 5 | 6 | 7 | 原文 :https://karpathy.github.io/2019/04/25/recipe/ 8 | 9 | 同时推荐作者的另一篇极好的博客: The Unreasonable Effectiveness of Recurrent Neural Networks 10 | https://karpathy.github.io/2015/05/21/rnn-effectiveness/ 11 | 12 | ---- 13 | ---- 14 | 15 | ## 1.神经网络经常无声无息的失败 16 | 17 | 1. 只有在运气好的时候,错误配置的神经网络才会抛出异常,大多数情况下,它会继续训练,但默默地使运行变糟。 18 | 19 | 例如: 20 | * 正则化强度 21 | * 学习率 22 | * 衰减率 23 | * 模型大小 24 | 等设置 25 | 26 | **Solve:** 对所有可能的事情进行可视化 27 | 28 | 29 | ## 2. 如何训练一个神经网络 30 | 31 | 从简单到复杂构建,每一步都要对将要发生的事情进行具体的假设,然后通过试验进行验证 32 | 33 | 34 | ### 1. 整理数据 35 | 36 | 1. 浏览数据,了解数据的分布: 37 | 数据中的重复,错误数据,数据的不平衡 等等 38 | 39 | 由于神经网络实际上是数据集的压缩/编译版本,因此你能够查看你的网络预测并了解它们可能来自何处。如果你的网络给你的预测与你在数据中看到的不一致,那就是有什么地方错了。 40 | 41 | 42 | 43 | ### 2. 建立 端到端的训练 44 | 45 | 我们希望训练这个网络,可视化损失,任何其他指标(例如准确性),模型预测,并在此过程中执行一系列带有明确假设的消融实验。 46 | 47 | 48 | **Tips** 49 | 50 | 51 | * 固定 random seed : 有利于得到相同的结果 52 | 53 | * 简化数据,先不要想着数据增强 54 | 55 | * 正确的初始化: 56 | 正确的初始化最后一层权重。 最后的回归值均值是50 ,我们在初始化的时候,设定 最后的 bias = 50 57 | 如果数据集不平衡,例如 positive: negative = 1:10 ,在 logits 上设定 偏置,使得网络预测的初始概率是 0.1. 并且消除 “hocky stick” 损失曲线(初始的几次迭代,网络只是在学习 bias) 58 | 59 | > 几种初始化 60 | uniform均匀分布初始化: 61 | w = np.random.uniform(low=-scale, high=scale, size=[n_in,n_out]) 62 | Xavier初始法,适用于普通激活函数(tanh,sigmoid):scale = np.sqrt(3/n)He初始化,适用于ReLU:scale = np.sqrt(6/n)normal高斯分布初始化: 63 | w = np.random.randn(n_in,n_out) * stdev # stdev为高斯分布的标准差,均值设为0 64 | Xavier初始法,适用于普通激活函数 (tanh,sigmoid):stdev = np.sqrt(n)He初始化,适用于ReLU:stdev = np.sqrt(2/n)svd初始化:对RNN有比较好的效果。 65 | 66 | 67 | 68 | * 人工 baseline : 69 | 70 | * input-indepent baseline。训练一个独立于输入的基线(例如,最简单的方法就是将所有输入设置为零)。这应该比实际插入数据而不将其归零的情况更糟。也就是说,可以知道你的模型是否学会从输入中提取任何信息? 71 | 72 | * 在单个批数据上过拟合。只过拟合包含少量例子(例如只有两个)的一个batch。为此,我们需要增加模型的大小(例如添加层或过滤器),并验证我们可以达到的最低损失值(例如0)。同一个图中可视化 label 和预测值,并确保一旦达到最小损失,它们最终会完美地对齐。如果没有完美对齐,那么在某个地方就有一个bug,我们无法继续到下一个阶段。 73 | 74 | * 验证训练损失的下降。在这个阶段,对于数据集建模很可能欠拟合,因为该阶段的模型是一个玩具模型。试着增加一点它的容量,在看看训练损失是否下降了。 75 | 76 | * 在模型预测之前进行可视化:可视化输入数据,labels,输出数据等 77 | 78 | * 可视化预测的动态结果: 在一个测试集上面 动态的可视化预测结果。 如果可视化的结果摆动太多次,可能是网络很难去拟合数据 79 | 80 | 81 | 82 | ### 3. 过拟合 83 | 84 | 在这个阶段,我们已经对数据集有一个很好的理解,同时我们有一个完整的训练-评估pipeline 85 | 86 | 找到一个好的模型可以分为两个阶段: 87 | 1. 首先 让模型尽可能的大,即使可能会过拟合,在这个过程我们只关心 training loss 88 | 2. 之后损失一些 training loss 提高 validation loss 89 | 90 | 使用这种方法的原因: 如果我们使用任何模型都没办法很小的 loss error, 说明我们的模型存在一定的问题。 91 | 92 | 93 | **Tips** 94 | 95 | * 选择合适的模型 : Don not be a hero: 不要急躁。 先去寻找最相关的文献,使用文献中的模型结构进行测试。然后再去自定义创造 layer 等 96 | 97 | * adam is safe: 早起设定baseline 的时候,通常选取 adam with 学习率 3E-04。 98 | 如果是RNN或者相关的序列模型, 最常用的就是 Adam 99 | 100 | * 从简单到复杂,如果有很的输入信号,每次只输入一个,或者先输入一个小的图片,再输入大的 101 | 102 | * 尽量减少使用默认的学习率下降: 如果是从其他领域哪来的代码直接应用,就要小心学习率下降, 103 | 可以使用 恒定的学习率 tune this all the way at the very end. 104 | 105 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/4x00z.png) 106 | 107 | 学习率太高,损失函数在某点开始震荡,不会收敛 108 | 学习率太低,模型将花费太长的时间来收敛。 109 | 110 | **寻找学习率的范围** 111 | 112 | 在每个 iteration 之后线性的增加 学习率,例如(1e-7 到 1e-1) 在每个 iteration之后,评估 loss。使用对数坐标绘制 loss 113 | 114 | The idea is to start with small learning rate (like 1e-4, 1e-3) and increase the learning rate after each mini-batch till loss starts exploding. 115 | 116 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/sgl0s.png) 117 | 118 | 梯度最陡的区域 即为最合适的 119 | 120 | > 训练集有1000个样本,batchsize=10,那么:训练完整个样本集需要:100次iteration,1次epoch。 121 | 122 | 123 | * 梯度剪裁: 限制最大的梯度 124 | 125 | 126 | 127 | 128 | 129 | 130 | ### 4. 调整 131 | 牺牲一些 training loss 提高 validation的精度 132 | 133 | **Tips** 134 | 135 | * 获取更多的真实数据 136 | 137 | * 数据增强:获得 half-fake data 138 | 139 | * 创造性数据增强。如果半假数据不能做到这一点,假数据也许可以。人们正在寻找扩展数据集的创新方法;例如,域随机化,模拟的使用,巧妙的混合,比如将(可能模拟的)数据引入场景,甚至是GAN中。 140 | 141 | * 进行预训练 142 | 143 | * 尽可能小的输入数据纬度 : 移除 spurious signal. 避免过拟合 144 | 145 | * 使用专业领域知识,限制网络的 size 146 | 147 | * 减小批大小。由于归一化是基于批大小的,更小的batch size会具有更明显的正则化效果。这是因为批量经验均值/标准是完整均值/标准的更近似版本,因此标度和偏移量“摆动”您的批次更多 148 | 149 | * dropout : 谨慎使用,一般设置为 0.5 150 | 对于RNN,建议放到输入->RNN与RNN->输出的位置. 151 | 152 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/qhvmb.png) 153 | 154 | * 使用 early stopping 155 | 156 | * batch-size: 可以设置 等于 1 157 | 158 | 159 | 160 | ### 5. 调参数 161 | 162 | * 随机网格搜索。为了同时调整多个超参数,使用网格搜索确保覆盖所有设置,这听起来很诱人,但请记住,最好使用随机搜索。直观地说,这是因为神经网络通常对某些参数比其他参数更敏感。在极限情况下,如果一个参数很重要,但是改变另一个参数没有效果,那还不如对第一个参数进行彻底采样。 163 | 164 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/7z6fx.png) 165 | 166 | * 超参数优化,目前很多基于贝叶斯的超参数优化工具箱 167 | 168 | 贝叶斯方法试图建立一个函数(更准确地说,是关于可能函数的概率分布),用于估计模型对于某个超参数选择的好坏程度。通过使用这种近似函数(在文献中称为代理函数),您不必在设置、训练、评估的循环上花费太多时间,因为你可以优化代理函数的超参数。 169 | 170 | 171 | 172 | ### 6. 优化提高 173 | 174 | * 集成 : 175 | 176 | 同样的参数,不同的初始化方式 177 | 不同的参数,通过cross-validation,选取最好的几组 178 | 同样的参数,模型训练的不同阶段,即不同迭代次数的模型。 179 | 不同的模型,进行线性融合. 例如RNN和传统模型. 180 | 181 | 182 | * 保持训练: 不要 validation loss 平稳就停止训练, 如果时间允许,一直训练可能会达到 state of the art 183 | 184 | * 如果你的模型包含全连接层(MLP),并且输入和输出大小一样,可以考虑将MLP替换成Highway Network,我尝试对结果有一点提升,建议作为最后提升模型的手段,原理很简单,就是给输出加了一个gate来控制信息的流动, 185 | 186 | 187 | ----- 188 | 189 | 190 | # 参考 191 | 192 | 1.https://karpathy.github.io/2015/05/21/rnn-effectiveness/ 193 | 2. https://blog.nanonets.com/hyperparameter-optimization/ 194 | 3. [Finding Good Learning Rate and The One Cycle Policy.](https://towardsdatascience.com/finding-good-learning-rate-and-the-one-cycle-policy-7159fe1db5d6) 195 | 4. https://www.zhihu.com/question/41631631 196 | 197 | -------------------------------------------------------------------------------- /Machine_Learning/罗辑回归.md: -------------------------------------------------------------------------------- 1 | 2 | * 原项目 link --https://github.com/Avik-Jain/100-Days-Of-ML-Code/blob/master/Code/Day%206%20Logistic%20Regression.md 3 | 4 | **本文是对原文的额一个汉化,以及相应的内容补充** 5 | 6 | * GitHub 项目链接 ---https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day4-5-6_Logistic_regression/README.md 7 | ----- 8 | 9 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/wdz01.jpg) 10 | 11 | --- 12 | 13 | 14 | 15 | 16 | 17 | # 1.逻辑回归 简要介绍 18 | 19 | ## 1 应用 20 | * 逻辑回归 用来处理不同的分类问题,----预测当前的值 属于哪个组 21 | * 给出一个类似于二进制结果(0,1)的输出 -----离散的输出结果(不同于线性回归的连续结果) 22 | 23 | ## 2 如何工作 24 | * 使用基础逻辑函数 通过估算概率来计算输出结果和一个或者多个特征之间的关系 25 | 26 | ## 3 作出预测 27 | * 将概率值转换为二进制的数 以便进行预测 28 | * 使用sigmoid函数 获得(0,1)的范围内结果 29 | * 阈值分类器 将(0,1)范围内的结果 转化为0或者1 30 | 31 | ## 4 sigmoid函数 32 | $$\theta(s)=\frac1{1+e^{-s}}$$ 33 | 34 | ## 5 极大似然估计 35 | 利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值。 36 | 37 | -------------- 38 | --------------- 39 | 40 | # 2. 基本原理 41 | ## 1 构造一个预测函数(h函数) :猜测预测函数的“大概”形式,比如是线性函数还是非线性函数。 42 | 43 | ### 1 使用 sigmoid函数 44 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/1l4va.jpg) 45 | 46 | ### 2 确定边界类型 47 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/yyj06.jpg) 48 | 49 | 50 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/bbxed.jpg) 51 | 52 | ### 3线性边界 53 | 54 | 1. 边界线 55 | 56 | $$\Theta ^{T}=\Theta_{0}+ \Theta_{1}x_{1}+\Theta_{2}x_{2}+...+\Theta_{n}x_{n}$$ 57 | 58 | 2.构造h函数 59 | $$h_{\Theta }(x)=\frac{1}{1+e^{-\Theta ^{T}x}}$$ 60 | h函数表示结果取1 的概率 61 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/8dsqi.jpg) 62 | 63 | ## 2 构造cost 函数:表示预测的输出(h)与训练数据类别(y)之间的偏差 64 | > 综合考虑所有训练数据的“损失”,将Cost求和或者求平均,记为J(θ)函数,表示所有训练数据预测值与实际类别的偏差。 65 | ![]() 66 | 67 | ### 1 使用最大似然估计推导 ---[详细](https://blog.csdn.net/ligang_csdn/article/details/53838743) 68 | 69 | ### 2 结果 70 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/i49ow.jpg) 71 | 72 | ## 3 使用梯度下降法求 J(theta)最小值 or 梯度上升求最大值 73 | 74 | ### 1梯度下降法表示theta更新过程 75 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/wgnfv.jpg) 76 | 77 | 结果: 78 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/j71b4.jpg) 79 | 80 | 81 | ## 4 梯度下降过程向量化 82 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/3tnnm.jpg) 83 | 84 | 85 | ---------------- 86 | ----------------- 87 | 88 | 89 | # 3 实操 90 | ## 1.实例 91 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/mvqcs.jpg) 92 | > 尝试预测哪些用户会购买这种全新SUV。并且在最后一列用来表示用户是否购买。我们将建立一种模型来预测用户是否购买这种SUV,该模型基于两个变量,分别是年龄和预计薪资。因此我们的特征矩阵将是这两列。我们尝试寻找用户年龄与预估薪资之间的某种相关性,以及他是否购买SUV的决定。 93 | 94 | ## Step 1 Data Pre-Processing-----[详见](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day1_Data_preprocessing/README.md) 95 | 96 | ```python 97 | 98 | import numpy as np 99 | import matplotlib.pyplot as plt 100 | import pandas as pd 101 | 102 | dataset = pd.read_csv('Social_Network_Ads.csv') 103 | X = dataset.iloc[:, [2, 3]].values ## 选取2,3两列--Age+ salary 104 | y = dataset.iloc[:, 4].values ## 选取最后一列 105 | 106 | from sklearn.cross_validation import train_test_split 107 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0) 108 | 109 | from sklearn.preprocessing import StandardScaler ##特征缩放 110 | sc = StandardScaler() 111 | X_train = sc.fit_transform(X_train) 112 | X_test = sc.transform(X_test) 113 | 114 | ``` 115 | 116 | > 117 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/uh0vu.jpg) 118 | 119 | ## Step 2 Logistic Regression Model 120 | * 逻辑回归应用于分类好的数据集 121 | ```python 122 | from sklearn.linear_model import LogisticRegression 123 | classifier = LogisticRegression() 124 | classifier.fit(X_train, y_train) 125 | ``` 126 | > LogisticRegression()函数有很多参数,详见[link](https://blog.csdn.net/CherDW/article/details/54891073) 127 | ## Step 3 Predection 128 | 129 | ```python 130 | y_pred = classifier.predict(X_test) 131 | 132 | ``` 133 | 134 | ## Step 4 Evaluating The Predection-------混淆矩阵等待解决???? 135 | 136 | ```python 137 | from sklearn.metrics import confusion_matrix 138 | cm = confusion_matrix(y_test, y_pred) 139 | ``` 140 | 141 | ## Step 5 visulisation 142 | > 原文无代码,但是有可视化结果,自行可视化-----其中[plot_decision_regions函数代码](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day4-5-6_Logistic_regression/plot_decison_regions.py) 143 | ```python 144 | plot_decision_regions(X_test, y_pred, classifier=cl) 145 | plt.xlabel('age') 146 | plt.ylabel('salary') 147 | plt.legend(loc='upper left') 148 | plt.title("Test set") 149 | plt.show() 150 | 151 | ``` 152 | 153 | ## 结果 154 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/96tay.jpg) 155 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/pxkox.jpg) 156 | 157 | ---------------------- 158 | --------------------- 159 | 160 | 161 | # 4 附录 162 | 163 | #### 1 [完整代码](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day4-5-6_Logistic_regression/logistic_regression.py) 164 | #### 2 [数据集](https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day4-5-6_Logistic_regression/Social_Network_Ads.csv) 165 | 166 | 167 | # 参考 168 | 1. 极大似然估计 : https://blog.csdn.net/zengxiantao1994/article/details/72787849 169 | 170 | 2. 数学推导以及图片来源: https://blog.csdn.net/ligang_csdn/article/details/53838743 171 | 172 | 3. 可视化: https://blog.csdn.net/xlinsist/article/details/51289825 173 | 174 | 4. logisticRegression() 函数参数: https://blog.csdn.net/CherDW/article/details/54891073 175 | -------------------------------------------------------------------------------- /Network_protocol/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Network_protocol/.DS_Store -------------------------------------------------------------------------------- /Network_protocol/网络协议- CDN 分发系统.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | > 上网的附近都有数据中心,数据中心里面部署一部分机器,形成一个缓存的集群来缓存部分数据,用户访问数据的时候,就可以**就近访问** 7 | 8 | --- 9 | 10 | ### 1. CDN 分发系统架构 11 | 12 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ogotl.jpg) 13 | 14 | 1. 边缘节点: 分布在各个地方的各个数据中心的节点 15 | 16 | 2. 区域节点: 规模更大,缓存的数据更多,命中的概率更高 17 | 18 | 3. 中心节点: 更大更多,如果还不命中,返回源网站访问 19 | 20 | ----- 21 | 22 | ### 2. 客户端如何找到相应的边缘节点 23 | > 类似于 基于 DNS 的全局负载均衡。 24 | 25 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/6qom6.jpg) 26 | 27 | 1. 存在 CDN 之后, 访问 www.web.com . 在 web.com 权威 DNS 服务器上,会设置一个 CNAME 别名,指向另一个域名 www.web.cdn.com 返回给 本地 DNS 服务器 28 | 29 | 2. 本地 DNS 服务器得到新的域名时候,解析这个域名; 接着访问 web.cdn.com 的权威 DNS服务器 30 | > 是 CDN 自己的权威 DNS 服务器,继续设置一个 CNAME,指向另一个域名---> CDN 的全局负载均衡 31 | 32 | 3. CDN 的 全局负载均衡器会为用户选择一台合适的缓存服务器提供服务 33 | * 根据 用户 IP 地址,判断哪一台服务器离得近 34 | * 根据用户的运营商 35 | * 根据 URL 中携带的内容名称,判断哪一台服务器上有用户的内容 36 | * 查询每个服务器的负载情况,哪一台还有服务能力 37 | 38 | 4. CDN 的 全局负载均衡器 返回一台缓存服务器的 IP 地址, 本地 DNS 服务器缓存这个 IP 地址,将 IP 返回给 客户端 39 | 40 | 5. 客户端访问中国边缘节点,下载资源,传送到终端 41 | 42 | 6. 如果边缘节点没有, 则向上一级请求 43 | 44 | ----- 45 | 46 | ### 3. CDN 缓存的内容 47 | 48 | #### 1. 流媒体 49 | 50 | * 流媒体是连续的,因此可以预先缓存,或者预先推送到用户的客户端 51 | 52 | * 流媒体的数据量大,出现向上一级拉取的情况,压力大,往往采取主动推送的模式,将热点数据轰动推送到边缘节点 53 | 54 | * CDN 提供 流媒体的预处理 55 | > 对视频进行分片,使得客户端可以选择不同的码率加载不同的分片 --- 超清 高清 流畅 56 | 57 | ---- 58 | 59 | ### 4. 动态 CDN 60 | 61 | #### 1. 边缘计算的模式 62 | * 将数据的逻辑计算和储存也放在边缘的节点,从源数据同步得到数据,在边缘节点计算 63 | 64 | #### 2. 路径优化 65 | 66 | * 数据的下发可以通过 CDN 网络对路径进行优化。 67 | > 能够找到离源站很近的边缘节点,找到离用户近的边缘节点。所以 可以选择一个更好的路径 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-HTTPS协议.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | > HTTPS 协议 : 需要加密的时候 HTTPS 7 | 8 | 9 | ## 1. HTTP 协议的保密 10 | 11 | ### 1. 对称加密 12 | > 对称加密算法中, 加密和解密使用的密钥是相同的 13 | 14 | * 约定一个密钥,发送请求的时候使用密钥进行加密;对应的使用密钥解密; 15 | > 但是约定的密钥也需要在互联网上传输,也有可能被截获 16 | 17 | 18 | ### 2. 非对称加密 19 | > 加密和解密的密钥不同, 一把是作为公开的公钥,另外一把是私钥,公钥加密的信息只有私钥可以解开,私钥加密只有公钥解开 20 | 21 | * 客户端和网站分别有 一对 公钥私钥, 22 | > 客户端发送的时候使用网站的公钥,网站给客户端发送消息时候,使用客户端的公钥。 23 | 24 | 25 | ### 3. 数字证书 26 | 27 | **如何鉴定公钥匙对的** 28 | 29 | 30 | * 先创建私钥,再创建对应的公钥,之后需要**证书**证明身份。 31 | 32 | * 证书里面; 33 | 34 | * 公钥 35 | * 证书发布机构和有效期 36 | 37 | * 证书的生成需要发起证书请求, 请求发送给权威机构认证 ----- 机构称为 CA - Certificate Authority 38 | 39 | * CA 使用自己的私钥给网站公钥签名,形成网站的证书 40 | 41 | * CA 公钥的 验证需要更上一层的 CA -- root CA **层层授信背书** 模式 42 | 43 | --- 44 | 45 | ## 2. HTTPS 的工作模式 46 | 47 | > 非对称加密的性能不如对称加密 48 | > HTTPS 将两者结合, 非对称加密主要用来传输对称加密的 密钥, 而双方数据的通信使用对称加密进行 49 | 50 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/1yc6n.jpg) 51 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/08zrg.jpg) 52 | 53 | 54 | 55 | 1. 客户端先发送 Client Hello 消息到服务器, 明文传输 TLS 版本信息,**加密套件候选**,压缩算法候选等信息,还有一个随机数 56 | 57 | 2. 服务器 返回 Sever Hello 消息,告知客户端,服务器使用的协议版本,加密套件,压缩算法,和一个随机数。 58 | 59 | 3. 之后 服务器发送一个 证书,之后发送 Sever Hello Done 60 | 61 | 4. 客户端进行 CA 检验,不断向上追溯 CA,直到一个授信的 CA 62 | 63 | 5. 证书验证通过,客户端计算产生随机数字 Pre-master, 使用证书中的公钥加密,Client key Exchange 发送给服务器,服务器通过私钥解密 64 | 65 | 6. 客户端和服务器现在都有三个随机数, 在服务器和客户端产生相同的**对称密钥** 66 | 67 | 7. 客户端发送 Change Clipher Spec, 以后都采用协商的通信密钥和加密算法,之后在发送一个 Encrypted Handshake Message ,使用协商密钥进行加密,发送给服务器用于数据与握手验证。 68 | 69 | 8. 同样,服务器也发送 Change Clipher Spec, 以后都采用协商的通信密钥和加密算法,之后在发送一个 Encrypted Handshake Message ,使用协商密钥进行加密,发送给客户端用于数据与握手验证。 70 | 71 | 9. 之后就可以通过对称密钥进行加密传输 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-HTTP协议.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | > HTTP 协议 : 上网协议 7 | 8 | 9 | ## 1. HTTP1.1 10 | 11 | ### 1. HTTP 请求准备 12 | 13 | * 浏览器将 域名 (例如: www.163.com )发送给 **DNS 服务器** 让他解析为 IP 地址。 14 | 15 | * HTTP 基于 TCP ; 首先建立 TCP 连接 16 | > 由于 HTTP 默认开启了 Keep-Alive, 这样建立的 TCP 连接可以在多次请求中复用 17 | 18 | ---- 19 | 20 | 21 | ### 2. HTTP 请求的构建 22 | 23 | * 建立连接之后,浏览器发送 HTTP 请求。 24 | 25 | 请求格式 26 | 27 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/2sfde.jpg) 28 | 29 | #### 1. 请求行 30 | 31 | * URL 是 http://www.163.com , 32 | 33 | * 方法 有几种常用的类型 : 34 | 35 | > 访问网页: **GET** ; 去服务器获取一些资源, 例如:网页,JSON 字符串 36 | > **POST** : 主动告知服务端一些信息 37 | >>> 例如 支付的时候,客户端就需要把 个人信息,支付金额等信息告诉服务器 38 | > **PUT** 向指定的资源位置上传最新的内容 39 | >>> 实际上使用的时候,HTTP 的服务器往往不允许上传文件, POST 用来创建一个资源,PUT 用来修改一个资源 40 | > **DELETE** : 删除资源 41 | 42 | #### 2. 首部字段 43 | 44 | 45 | * Accept-Charset: 表示客户端可以接受的字符集 46 | 47 | * Content-Type : 表示正文的格式,例如 JSON 48 | 49 | * 缓存 50 | > 对于一个页面,会有很多数据,每次更新数据有些静态资源不一定要每次都更新 51 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/1l995.jpg) 52 | * Nginx 处理 HTTP 协议, 对于静态资源,有 Vanish 缓存层,当缓存过期的时候,才会访问 Tomcat 应用集群 53 | 54 | * Cacha-control 用来控制缓存 55 | > 例如客户端发送的请求中包含 max-age, 如果缓存层中,资源的缓存时间数值小于 max-age ,客户端可以接受缓存的资源,如果 age = 0 ; 缓存层将请求直接转发给应用集群 56 | 57 | * If-Modified-Since : 如果服务器的资源更新了,那么客户端也应该下载最新的资源 58 | 59 | ---- 60 | 61 | ### 3. HTTP 请求的发送 62 | 63 | 1. 使用面向连接的方式发送请求, 通过 Stream 二进制流的方式传送, 传送到 TCP 层, 二进制流转化成一个报文段发送给服务器。 64 | 65 | 2. 发送每个报文段, 都需要对方一个回应 ACK ,保证报文的准确到达。 66 | 67 | 3. TCP 层 发送报文,需要加入自己的地址,和目的地址,地址再加入到 IP头里面,交给 IP 层进行传输 68 | 69 | 4. IP 层查看目标地址和自己是否在 同一个局域网里面 ? 70 | * 如果是 发送 ARP 协议请求目标地址的 MAC 地址,将源 MAC 地址和目标 MAC 放入 MAC 头,发送出去 71 | * 如果不是, 需要发送网关,使用 ARP 协议获取网关的 MAC 地址,放入MAC 地址发送出去;网关首发哦包发现 MAC 符合,取出 IP地址,根据协议找到下一跳的路由器,获取下一跳路由器的 MAC 地址,包发给下一跳路由器 72 | ; 一跳一跳到达目的局域网, 在局域网发送 ARP ,获得 目标地址的 MAC地址发送 73 | 74 | 5. 目标机器发现 MAC 地址符合,将包收起来,发现 IP 地址符合,根据 IP 头中的协议,知道上一层是 TCP 协议,解析 TCP 的头,;打开序列号,判断序列包是不是需要的,如果是就放入缓存中返回 ACK 75 | 76 | 6. TCP 里面包含端口号, HTTP 的服务器正在坚挺这个端口号;目标机器知道是HTTP 服务器这个进程需要这个包, 将包发送给 HTTP 服务器。HTTP 服务器的进程看到,知道请求是访问一个网页,将网页发送给客户端。 77 | 78 | ---- 79 | 80 | ### 4. HTTP 返回 81 | 82 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/175ni.jpg) 83 | 84 | #### 1. 状态码: 反应 HTTP 请求结果 85 | * 200 意味着 一切顺利 86 | * 404 意味着 服务端无法响应这个请求 87 | * 503 服务暂时不再和 Retry-After 一起使用 88 | 89 | #### 2. 短语 : 大概叙说一下原因 90 | 91 | 92 | #### 3. 首部的 Key-Value 93 | 94 | * Retry-After : 客户端应该在多长时间后再次尝试 95 | 96 | * Content-Type : 表示返回 HTML 还是 JSON 97 | 98 | 99 | #### 4. 发送 HTTP 的 返回报文 100 | 101 | * 报文交给 Socket 发送,交给 TCP 层,让 TCP 层将返回的 HTML 分成一个个小的段,保证每个段都可到达 102 | 103 | * 类似于上文,反向过程走一遍,一直到达客户端 104 | 105 | * 客户端发现 MAC 地址符合 IP地址符合,交给 TCP 层,判断序列号是不是自己需要的报文段,如果是,根据 TCP 的端口号,发给相应的进程。 进程就是浏览器,浏览器作为客户端监听端口 106 | 107 | * 浏览器 收到 HTTP 的报文,如果是 200 , 就从正文中拿出 HTML,展示网页 108 | 109 | 110 | ----- 111 | 112 | ## 2. HTTP 2.0 113 | 114 | * 2.0 对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引 115 | 116 | * 一个 TCP 连接,切分成多个流, ,每个流都有自己的 ID,并且分优先级 117 | 118 | * 将 所有的传输信息分割为更小的消息和帧, 帧可以打散乱序发送,然后根据每个帧的首部流标识符重新组装并且可以根据优先级,决定优先处理哪个流的数据 119 | 120 | * HTTP1.0 请求是串行的,使用 HTTP2.0 ,在一个连接里面客户端和服务端都可以同时发送多个请求和回应,而且不用按照顺序一一对应 121 | 122 | 123 | 124 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/i20lc.jpg) 125 | 126 | * HTTP 2.0 将三个请求变成3个流,数据分成帧,乱序发送到一个 TCP 连接之中 127 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/5if6g.jpg) 128 | 129 | 130 | ----- 131 | 132 | 133 | ## 3. QUIC 协议 134 | 135 | * HTTP 2.0 协议增加了并发性,但是因为也是基于 TCP 协议, 处理包的时候有严格的顺序,一个数据包遇到问题的时候,需要等待这个包完成重传才能继续进行 136 | 137 | ### 1.自定义连接机制 138 | 139 | * 一条 TCP 连接是由四元组标识的,分别是 源 IP,目的 IP, 源端口,目的端口,一个元素发生变化,就需要断开重新连接,信号不稳定,网络切换,导致重连,导致时延。 140 | 141 | * 在 QUIC 之中, 不再以四元组标识, 而是以一个 64位的随机数作为 ID 来标识,UDP 无连接,只要 ID不变,就不需要重新连接 142 | 143 | 144 | ### 2. 自定义重新连接 145 | 146 | * QUIC 定义了 offset 的概念,数据在数据流里面有一个 偏移量,通过 offset 查看数据发送位置 147 | 148 | 149 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/0xxzw.jpg) 150 | 151 | 152 | ### 3. 自定义流量控制 153 | 154 | * QUIC 的 ACK 是基于 offset,offset包进来,进入缓存,可以应答 155 | 156 | > TCP 的 ACK 机制基于序列号的累积应答,ACK一个序列号,就能说明前面的都到了,所以,一旦有一个每个后面的到了也不能 ACK;导致后面的到了也可能超时重传,浪费带宽。而 QUIC 中间可以村子啊空档 157 | 158 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/kuk43.jpg) 159 | 160 | 161 | ------- 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-ICMP.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | ### ICMP 协议 --- 互联网控制报文协议 7 | 8 | > 网络包在异常复杂的网络环境中传输,会遇到各种问题,需要传回问题的信息 9 | 10 | * ICMP的报文封装在 IP 的包里面 11 | 12 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/g526u.jpg) 13 | 14 | > ICMP.的报文有很多的类型,不同的类型有不同的代码。 最常用类型是主动请求8 ,主动请求的应答为 0 15 | 16 | ---- 17 | 18 | ### 查询报文的类型 19 | 20 | * 常用的 ping 是查询报文,是一种主动请求,并且获得主动应答的 ICMP 协议 。 21 | 22 | * 对 ping 的主动请求进行网络抓包 -- ICMP ECHO REAUEST; 主动请求的回复 ---- ICMP ECHO REPLY 23 | 24 | * 相比于 原声的ICMP,多了两个字段 ; 一个是标识符 ; 一个是序号 25 | > 去两队侦查兵,一队是侦查战况的,一队是去查找水源的,要有个标识才能区分。另一个是序号,派出去10个回来10个 就说明状况不错 26 | 27 | 28 | ### 差错报文类型 29 | 30 | > 异常情况发起的,报告发生了不好的事情 31 | 32 | 33 | * 终点不可达 -- 3 : 34 | * 网络不可达 0 : 找不到地方 35 | * 主机不可达 1 :找到地方没人 36 | * 协议不可达 2 : 找到地方找到人, 对不上协议 37 | * 端口不可达 3 : 38 | * 需要进行分片单设置了不分片位: 39 | 40 | * 源站抑制 --- 4 : 41 | > 让源站放慢发送速度 42 | 43 | * 时间超时 -- 11 : 44 | > 超过网络包生存时间还没送到 45 | 46 | * 路由重定向 -- 5 : 47 | > 下次发给另一个路由器 48 | 49 | ----- 50 | 51 | ### ping : 查询报文类型: 52 | 53 | #### 1. 同一个局域网 54 | 55 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/8u5sz.jpg) 56 | 57 | * 源主机首先会构建一个 ICMP请求数据包,ICMP 数据包含: 58 | * 类型字段: 请求数据包 字段为8 59 | * 顺序号 : 区分连续 ping 时候发出的多个数据包,每发出一个,顺序号会自动加1 60 | * 计算往返时间 RTT 报文的数据部分加入发送时间 61 | 62 | * 在规定的时间内,源主机如果没有接到ICMP 的应答包,则说明主机不可达; 如果接收到了 ICMP 应答包,则说明目标主机可达 63 | 64 | #### 2. 跨网段 65 | 66 | * 涉及网关的转发和路由器的转发等 67 | 68 | #### 3. 可控范围 69 | 70 | * 需要一个网络拓扑图 : 清楚的知道一个网络包从源地址到目标地址需要经过哪些设备, 逐个 ping 这些设备 71 | 72 | ---- 73 | 74 | ### Traceroute 75 | 76 | > 暂留 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-P2P协议.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | ### 1. FTP(文件传输协议) 下载文件 7 | > 采用两个 **TCP**连接传输一个文件 8 | 9 | * 一 控制连接:服务器被动打开用于 FTP 的端口 21,客户端主动发起连接 10 | 11 | * 二 数据连接: 每当一个文件在客户端和服务器之间传输的时候,就创建一个数据连接 12 | 13 | **FTP 两种工作模式** 14 | 15 | * 主动模式 PORT: 16 | > 客户端随机打开一个 大于1024 的端口 N,向服务器的端口 21 发起连接; 同时开放 N+1 端口进行监听,向服务器发出 “port N+1”,服务器从自己的数据端口20 主动连接到客户端的端口 N+1 17 | 18 | * 被动模式 PASV: 19 | > 开启一个 FTP 连接, 客户端打开两个任意的 本地端口 N和 N+ 1 (大于 1024)。 第一个端口连接服务器的 21 端口,提交 PASV命令。 服务器会开启一个任意端口 P(大于 1024),返回 “227 entering passive mode”消息,包含FTP开放数据传输的端口。 之后客户端的 N+1号端口会连接到服务器的端口 P,端口之间进行数据传输。 20 | 21 | ---- 22 | 23 | ### 2. P2P peer-to-peer 24 | > 资源不是集中在某些设备上,而是分散在储存在多台设备上。设备可以称为 peer 25 | 26 | * 下载文件的时候,只需要得到存在文件的 peer,并和 peer 之间建立点对点的连接(不需要到中心服务器上面),就可以就近下载文件 27 | 28 | * 下载文件之后,也变成了 peer 中的一员, 也可以给别人提供下载 29 | 30 | --- 31 | 32 | ### 3. 种子文件 .torrent 33 | 34 | **如何知道哪些peer 有文件是一个关键问题** 35 | 36 | #### 1. 种子文件简介 37 | 38 | * 文件由 两部分组成 : announce(tracker URL) 和 文件信息 39 | 40 | * 文件信息中 包含: 41 | * Info 区: 说明种子有几个文件,文件多大, 目录结构,以及目录和文件的名字。 42 | * Name 字段: 制定顶层目录的名字 43 | * 每个段的大小 : BitTorrent (BT) 协议,把文件分成很多个小段,然后分段下载 44 | * 段哈希值 : 将整个种子中,每个段 SHA-1 哈希值拼在一起 45 | 46 | #### 2. 下载 过程 47 | 48 | 1. BT 客户端 解析 .torrent 文件,得到 tracker地址,连接成、tracker服务器。 49 | 50 | 2. tracker服务器将其他下载这的 IP提供给 下载的人, 51 | 52 | 3. 下载者连接其他的下载者,根据 .torrent 文件,两者分别告知对方已经有的块,然后交换对方没有的数据 53 | 54 | #### 3. tracker 55 | 56 | * tracker 需要收集下载者的信息,并将信息提供给其他的下载者 57 | 58 | * 下载的过程是去中心化的,但是加入 P2P 的网络还是需要借助 **tracker 中心服务器** 59 | 60 | ---- 61 | 62 | ### 4. 去中心化网络 DHT -- Distributed Hash Table 63 | > 每个加入 DHT网络的人,都要负责储存网络里面的资源和其他成员的联系信息 64 | 65 | **暂留** 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-TCP和UDP.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | 7 | ### 1. TCP 和 UDP 的区别简述 8 | 9 | 10 | * TCP 是面向连接的,面向连接的协议会先建立连接 11 | > 建立连接 : 为了在客户顿啊和服务算维护联机玩,而建立一定的数据结构维护双方交互的状态, 12 | 13 | * 通过 TCP 连接传输的数据,**无差错,不丢失,不重复**; 而 UDP 和 IP 包一样,**不保证不丢失,不保证按照顺序到达**; 14 | 15 | * TCP 是面向**字节流**的,发送的时候发的是一个流,没头没尾;; 而 UDP 继承了 IP的特性 基于数据包,**一个一个的发** 16 | 17 | * TCP 有 拥赛控制的,当包丢弃了或者网络环境不好,根据情况调整自己的行为, UDP 不会 18 | 19 | ---- 20 | 21 | 22 | ### 2. UDP 包的 头 23 | 24 | > 发送的 UDP 包到达目的机器后, 匹配 MAC 地址之后,取下 MAC 地址,将剩下的包传给 处理 IP层的代码, 把IP头 取下来, 发现 IP匹配 25 | 26 | * 发送包的时候有一个 8 位的协议, 数据是 TCP 还是 UDP;知道了 UDP 的格式,就可以解析出来,之后数据交给应用程序 27 | 28 | * 应用程序会监听一个端口,不同的应用程序对应不同的端口号, TCP 和 UDP 里面含有端口号,根据端口号,将数据交给相应的应用程序 29 | 30 | 31 | ---- 32 | 33 | ### 3. UDP 的特点 34 | 35 | * 不会建立连接,虽然有端口号,但是在监听的地方,谁都可以给他传输数据,他也可以传给任何人数据,同时传给多人数据 36 | 37 | * 没有拥塞机制,网络包丢了,还会一直一直的发 38 | 39 | --- 40 | 41 | ### 4. UDP 使用场景 42 | 43 | * 网络环境好(内网), 丢包不敏感 44 | 45 | * 可以广播或者组播的应用 46 | > 多播-组播 : 组播地址,使用这个地址,可以将包组播给一批机器。 47 | 48 | * 处理速度快,**低延时**一直发送, 不太在意丢包的应用 49 | 50 | ------ 51 | 52 | 53 | ### 5. UDP 的应用实例 54 | 55 | 56 | ##### 1. 网页或者 APP 的访问 57 | 58 | * 原本网页访问 都是基于 HTTP协议, 而 HTTP 协议是基于 TCP的,建立连接需要多次的交互;而且 TCP 严格的顺序策略是的共享通道中,前一个不来,后一个和前一个没关系也要等着,延时加大 59 | 60 | * QUIC Quick UDP Internet COnnections,快速UDP 互联网连接) ---- 谷歌的改进通信协议,减少网络通信的延时。 61 | 62 | 63 | 64 | ##### 2. 流媒体的协议 65 | 66 | > 直播的协议多是 RTMP 67 | 68 | * RTMP 协议基于 TCP ,有着严格的传输顺序,起那一个不到,下一个到了 也不行 69 | 70 | * 而且 对于视频播放,有的包可以丢, 隔几个帧丢一个包,不太会发现、 71 | 72 | * TCP 在网络不好的时候,主动降低发送的速度, 本来就卡,会跟家卡 73 | 74 | **直播应用现都是基于UDP实现视频传输协议** 75 | 76 | ##### 3. 实时游戏 77 | 78 | > 对战游戏, 玩家通过客户端发送给服务器鼠标和键盘的位置,服务器处理每个用户发来的场景,处理完饭回客户端,客户端解析相应,渲染最新的场景展示给玩家 79 | 80 | * 实时游戏需要客户端和服务器建立长连接,保证实时传输,一台机器能够支撑的TCP连接数目有限,,而 UDP没有连接,可以应对海量客户端 81 | 82 | * TCP 强顺序,出现一个数据包丢失,所有数据都要等待这个数据包重发,客户端等待接收数据,会卡顿 83 | 84 | 85 | ##### 4. 物联网 86 | 87 | * 物联网对实时性要求较高, TCP 延时较大 88 | 89 | * 物联网终端资源少,维护TCP协议代价大 90 | 91 | 92 | ##### 5. 移动通信领域 93 | 94 | 暂无 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-ip地址.md: -------------------------------------------------------------------------------- 1 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 2 | 3 | --- 4 | 5 | 6 | ### 1. 查询 IP 地址 7 | 8 | * IP 地址是一个网卡在网络世界的通讯地址,相当于门牌号码,每个人应该都不一样。 9 | > 有时候电脑弹出网络地址冲突,上不去网,多半是 IP地址冲突 10 | 11 | ```python 12 | $ ifconfig # linux 13 | $ ip addr # linux 14 | 15 | $ ipconfig # windows 16 | 17 | ``` 18 | 19 | ### 2. 运行 ifconfig,输出 20 | ``` 21 | lo0: flags=8049 mtu 16384 22 | options=1203 23 | inet 127.0.0.1 netmask 0xff000000 24 | inet6 ::1 prefixlen 128 25 | inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 26 | nd6 options=201 27 | gif0: flags=8010 mtu 1280 28 | stf0: flags=0<> mtu 1280 29 | XHC20: flags=0<> mtu 0 30 | XHC0: flags=0<> mtu 0 31 | 32 | 33 | en0: flags=8863 mtu 1500 34 | ether 88:e9:fe:4f:1a:da 35 | inet6 fe80::1847:2eb3:3b44:bc47%en0 prefixlen 64 secured scopeid 0x6 36 | inet 172.20.10.4 netmask 0xfffffff0 broadcast 172.20.10.15 37 | inet6 2409:8915:1c12:334a:8dc:f8ec:6219:1cdc prefixlen 64 autoconf secured 38 | inet6 2409:8915:1c12:334a:e0fb:3a4:2a22:57e0 prefixlen 64 autoconf temporary 39 | nd6 options=201 40 | media: autoselect 41 | status: active 42 | 43 | ``` 44 | 45 | * lo 全称是loopback,又称环回接口,往往会被分配到127.0.0.1 这个地址。这个地址用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。 46 | 47 | 48 | * 第一行: en0 表示第一块网卡) UP (代表网络开启),BROADCAST (网卡有广播地址,可以发送广播包),SMART,RUNNING(网卡的网线被接上),SIMPLEX,MULTICAST(支持组播)mtu 1500(最大传输单元: 1500字节) 49 | 50 | * 第二行: ether(网络连接类型是 以太网连接) 88:e9:fe:4f:1a:da (mac地址) 51 | 52 | * 第三行 :ipv6 的网络地址 : fe80::1847:2eb3:3b44:bc47 有128位 53 | 54 | * 第四行: **IP 地址** 172.20.10.4 地址有四个部分,每部分8个 bit,总共 32 位 ; netmask(掩码地址); broadcast(广播地址) 55 | 56 | ### 3. ip 地址的分类 57 | 58 | 59 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/smmb4.jpg) 60 | 61 | * 主要分为两部分 : 网络号 + 主机号 62 | 63 | 64 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/i4r6j.jpg) 65 | 66 | 67 | * 对于 A 类: IP 地址范围 : 地址的第一个部分为网络号 1位固定为 0 ;7位可选, 2的7次方 共 128个即 0--127,剩余三部分,每部分8位 256个,0:255 68 | 69 | * 对于 B 类: 网络号,有 6+ 8 位 即: 64 ,256 对应前面两部分 128-191 和 0 -- 255 ;主机号8 + 8 位 70 | 71 | * 对于 C 类: 网络号 5+ 8+ 8。即: 32 + 256 + 256 ;主机号 8 位 对应 256 个主机 72 | 73 | > C 类地址包含主机数目太少, B类地址包含主机数目太多, 需 6 万多台机器,会有很多闲置地址 74 | 75 | 76 | ### 4. 无类型域间选路(CIDR) 77 | 78 | * 将32 位的 IP 地址 一分为2 前面是网络号,后面是主机号 79 | > 例如 :10.100.122.2/24。斜杠后面的 24 表示 前24 位 是网络号,后8位是主机号 80 | 81 | * 伴随 CIDR 存在的有 广播地址 172.20.10.15,发送这个地址,所有172.20.10 网络里面的机器都可以收到 82 | 83 | * 子网掩码地址 :0xfffffff0 对应于 255.255.255.240 84 | 85 | > /24 255.255.255.0 0xffffff00 11111111 11111111 11111111 00000000 86 | > /28 255.255.255.240 0xfffffff0 11111111 11111111 11111111 11110000 87 | 88 | * 网络号 ; 子网掩码和 IP地址安位计算 AND : 得到 172.20.10.0 就是网络号 89 | 90 | 91 | **16.158.165.91/22 这个 CIDR 22不是8 的整数倍,,需要转换为 二进制求解** 92 | 93 | 94 | ### 5. 公有 IP 和 私有 IP 95 | 96 | 97 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/i4r6j.jpg) 98 | 99 | 100 | * 家庭 学校,等 一般都是私有 IP ,私有 IP 允许 重复 101 | > 小区有自己的楼编号和门牌号,你们小区可以叫 6 栋,我们小区也可以叫6栋 102 | 103 | * 局域使用,例如学校,私有 IP 即可; 公有 ip 全世界访问,需要购买 104 | 105 | * 192.168.0.x 是最常有的 私有 IP 地址 106 | > 192.168.0 是网络号,后面是主机号。而整个网络里面的的第一个地址 192.168.0.1,往往就是私有网络的出口地址 107 | > Wi-Fi 路由器的地址就是。192.168.0.1 ,而 192.168.0.255 就是广播地址,放松这个地址,网络里面所有的机器都能收到 108 | 109 | 110 | ### 6. MAC 地址 111 | 112 | > ether 88:e9:fe:4f:1a:da 113 | 114 | * 网卡的物理地址, 16进制 6 个 byte 115 | 116 | * MAC 地址 全局唯一,不会有两个网卡有相同的 MAC。网卡自生产出来就带着这个地址 117 | 118 | * 但是 不能 仅使用 MAC 地址进行通信。 需要 IP 地址的 远程定位功能 119 | 120 | > MAC 地址更像 身份证,IP 地址 像 居住或者所在的位置信息 121 | 122 | * MAc 地址的通信范围 局限在一个 子网里面 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | # 参考 136 | 137 | 138 | 1. 每天一个linux命令(52):ifconfig命令----https://www.cnblogs.com/peida/archive/2013/02/27/2934525.html 139 | 140 | 2. 极客时间: https://time.geekbang.org/column/article/7772 141 | 142 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-交换机和STP.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | --- 5 | 6 | * 多台交换机连接会形成一个拓扑结构 7 | 8 | 9 | ### 两台交换机 -- 广播 10 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/hkhru.jpg) 11 | 12 | * 机器1想要知道 机器4的 MAC 地址 13 | > 机器 1 进行广播,交换机 A也收到广播,但是不知道任何的拓扑信息,所以除了广播包来的方向外,转发给其他的所有的网口,机器3接收到广播消息,交换机B接收到广播信息,将包转发的局域网3, 机器4和机器5 收到广播信息,机器4主动响应,提供 MAC 地址。 14 | 15 | > 这个过程 交换机 A 和 交换机B 记住机器1 的网口。当接下来机器3 访问机器1 的时候,广播 ARP的请求, A收到请求后知道机器1 的位置,将消息广播到局域网一,交换机B接收到广播消息后,知道不在,所以不会广播。 16 | 17 | ---- 18 | 19 | 20 | ### 交换机 -- 环路问题 21 | > 两台交换机将两个局域网同时连接起来 22 | 23 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/4abqv.jpg) 24 | 25 | * 对于机器1访问机器2 的过程 26 | > 两个交换机都能接收到广播消息,交换机A不知道机器2在哪个局域网,将广播消息放到局域网2 ,交换机B 从局域网2 得到消息传到局域网1 ,从左边传入A,形成循环。 27 | 28 | * 环形结构 学习不到 拓扑结构。 29 | 30 | 31 | ---- 32 | 33 | 34 | ### STP 协议基本概念 --- Spanning Tree Protocol 35 | 36 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/w64le.jpg) 37 | 38 | * Root Bridge : 根交换机 39 | 40 | * Designated Bridges : 指定交换机;树的树枝,其他的交换机通过他到达根交换机 41 | 42 | * Bridge Protocol Data Units (BPDU) 网桥协议数据单元,只有 根交换机可以发,其他的交换机发自己上层的交换机的协议 43 | 44 | * Priority Vector,优先级向量; [Root Bridge ID, Root Path Cost,Bridge ID ,Port ID] 45 | > 先比较 跟交换机 ID, 如果 ID 一样,比较 和根交换机的距离。比较自身的 ID。 46 | 47 | 48 | ----- 49 | 50 | ### STP 工作过程 51 | 52 | #### 1. 初始 53 | 54 | * 初始的时候,所有的交换机都是 RootBridge, 每个交换机有不同的分配的优先级 55 | 56 | * 每个 网桥也有不同的ID 不同的优先级 57 | 58 | * 都是 RootBridge,互相会发送BPDU ,赢得是 RB 输的是 DB。 输了的 DB 智能 转发 RB 的BPDU 59 | 60 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/qjndz.jpg) 61 | 62 | > 形成 5-6, 1-7, 2-8 ,3-4 这样的的一个个小部分 63 | 64 | 65 | #### 2. 合并 66 | 67 | * 当 5 碰到了 1 , 都是RB, 1的优先级高, 1567合并 68 | 69 | * 1 和 6 相遇, 1567 已经合并, 原本就是 一支,但是 6 距离1 是2 ,而 从5的那一路走是 4+ 1 =5 所以5,6 不在分上下 70 | 71 | * 当 5,6 再相遇, 5 发现从6 走的距离是3 ,所以6 称为5 的上支 72 | 73 | * 2 和7 相遇, 2 比7 强,但是 7 的上层1 比1 强 ,所以 2 成为 1的分支 74 | 75 | * 5 和 4 相遇, 5 的上层是1 , 4 的上层是3。,4 要加入5 76 | 77 | * 最终生成一棵树 78 | 79 | 80 | 81 | #### 3. 广播问题和安全问题 82 | 83 | * 在同一个广播域里面,很多包都会在一个局域网里面传播, 很容易泄露 84 | 85 | 86 | 87 | #### 4. 虚拟隔离 --- VLAN。虚拟局域网 88 | 89 | * 一个交换机会连接属于多个局域网的机器, 通过 Tag 的 VLAN ID 区分 哪个机器属于哪个局域网 90 | 91 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/8m9b2.jpg) 92 | 93 | 94 | * 只有 相同 VLAN的包 才会互相转发,不同 VLAN的包互相看不到 95 | 96 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/xxw8d.jpg) 97 | 98 | > 例如程序员的口 VLAN10 , 财务 VLAN 30 99 | 100 | > 交换机之间的 连接使用 TRUNK 口, 转发属于任何 VLAN的口 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-数据中心.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | 7 | ### 1. 数据中心 8 | 9 | 数据中心的入口和出口是路由器,在数据中心放入边界,称为**边界路由器**。 为了高可用,数据中心的边界路由器会连接多个运营商网络。 10 | 11 | 路由器需要跑路由协议,数据中心是路由协议中的自治区域(AS)。数据中心的机器访问外面的网站,可以通过 BGP 协议,获取内外胡同的路由信息 12 | 13 | 14 | 15 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/3hzmg.jpg) 16 | 17 | 18 | 如果数据中的机器非常多,需要有交换机将服务器连接起来,互相通信 19 | > 交换机通常放在机架的顶端,称为 TOR交换机 -- Top Of Rack, 20 | 21 | 当存在多个机架的时候,需要交换机将多个机架连接在一起 ---- **汇聚交换机** 22 | > 对性能要求更高,带宽更大 23 | 24 | 数据中心里面的每个连接都是需要考虑高可用。一台机器至少需要两个网卡,两个网线插到 TOR交换机上,但是需要工作的像一张网卡,需要网卡绑定(bond) 25 | 26 | ----- 27 | 28 | 服务器和交换机支持一种协议 LACP(Link Aggregation Control Protocol)。 互相通信,多个网卡聚合成一个网卡,多个网线聚合成为一个网线,在网线之间进行负载平衡,**网卡高可用** 29 | 30 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/pqeuw.jpg) 31 | 32 | **交换机高可用** 33 | > 如果一个机架只有一个交换机,交换机挂了,整个机架也不能上网 34 | 35 | * 部署两个交换机,两个汇聚交换机,接入交换机和两个汇聚连接,形成环,需要启用 STP 协议,去除环。 36 | 37 | 38 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/flgfa.jpg) 39 | 40 | * 交换机使用堆叠技术, 形成双活的连接方式 41 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/gqnqm.jpg) 42 | 43 | 44 | ---- 45 | 46 | ### 2.整个数据网络 47 | 48 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/nmvlk.jpg) 49 | 50 | 51 | 52 | ----- 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-流媒体协议.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | > 只介绍视频传输,没有音频 !!! 7 | 8 | --- 9 | 10 | 11 | ### 1. 视频大小 12 | 13 | 1. 每一张图片称为一 帧 14 | 15 | 2. 每一张图片都是由像素组成的,假设1024* 768, 16 | 17 | 3. 每个像素由 RGB组成, 每个 8位,共24位 18 | 19 | 4. 一秒钟 : 30 帧 * 1024* 768 * 24 = 7077888Bytes 20 | 21 | 5. 一分钟 : 约 4 个 G 22 | 23 | ---- 24 | 25 | ### 2. 编码-- 压缩视频 26 | 27 | #### 1. 能够编码的原因 28 | 29 | 1. 空间冗余 : 图像的相邻像素之间存在较强的相关性,可以隔几个保存一个,中间的使用算法及孙啊出来 30 | 31 | 2. 时间冗余: 视频序列的相邻图像之间内容相似,可以预测和推断 32 | 33 | 3. 视觉冗余: 人眼对某些细节并不敏感,可以丢失一些细节 34 | 35 | 4. 编码冗余 :不同像素值出现的概率不同, 概率高的字节少,概率低的字节多 36 | 37 | 38 | #### 2. 编码过程 39 | 40 | 41 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/oar7v.jpg) 42 | 43 | 44 | #### 3. 视频编码的主要流派 45 | 46 | * 一: 国际电联的 VCEG --- 侧重传输 47 | > H.261, H.264 等等就是这个组织制定的标准 48 | 49 | * 二: ISO 的 MPEG --- 侧重于 视频储存 50 | > MPEG-1 , M PEG-2 等 就是这个组织制定的标准 51 | 52 | 53 | **ITU 和 MPEG 联合制定了H.264/MPEG-4 AVC** 54 | 55 | > 编码之后, 图像转换为二进制,以一定的格式保存,例如:AVI , MPEG RMVB MP4.。。。。 56 | 57 | 58 | 59 | ---- 60 | 61 | 62 | ### 3. 网络传输 --- 直播 63 | 64 | 65 | #### 1. 过程 66 | 67 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/k57rd.jpg) 68 | 69 | ##### 1. 接流 70 | 71 | * 网络协议将编码好的 视频流,从主播端推送到服务器,在服务器上面有运行着同样协议的服务端接受网络包, 从而得到里面的视频流 72 | 73 | ##### 2. 流处理 74 | 75 | * 服务端收到视频流之后, 视频进行转码,从一个编码格式转换为另一种编码格式, 对应不同的客户端 76 | 77 | ##### 3. 拉流 78 | 79 | * 观众的客户端请求过程称为 拉流 80 | 81 | ##### 4. 分发 82 | 83 | * 观众多,都从一个服务器上拉流对服务器压力太大, 需要视频分发网络,视频预先加载到边缘节点, 从边缘节点拉取 84 | 85 | ##### 5. 解码 86 | 87 | * 拉取到视频流之后,将二进制转换成图片播放 88 | 89 | ------ 90 | 91 | #### 2. 编码 92 | 93 | 将视频序列分为三种帧 94 | 95 | * I 帧 : 关键帧, 包含完整的图片 96 | 97 | * P 帧: 前向预测编码帧。包含的是这一帧和之前一个关键帧(或者P 帧)的差别,解码需要之前的画面 98 | 99 | * B 帧 : 双向预测内插编码帧。 包含本帧和前后帧之间的差别。 解码需要之前缓存的画面还需要之后的画面 100 | 101 | ##### 1. 通过时序进行编码 102 | 103 | * IBBP 序列 104 | 105 | ##### 2. 空间上 编码 106 | * 帧 --> 片 --- > 宏块 --> 子块 107 | 108 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/a4xtw.jpg) 109 | 110 | 111 | ##### 3. 压缩成 二进制流 112 | 113 | * 流是一个个网络提取单元 NALU (Network ABstraction Layer Unit), 为了便于包的传输,分成一个个单元 114 | 115 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/65lcj.jpg) 116 | 117 | 1. NALU 前部一个 起始标识符-- 标识 NALU 之间的间隔 118 | 119 | 2. NALU 头: 包含 不同的类型 120 | 121 | * SPS : 序列参数集 包含一个图像序列所有信息,图像的大小,视频的格式 122 | 123 | * PPS : 图像参数集 包含图像 的所有分片的所有相关信息,图像的类型,序列号 124 | 125 | **为了保证容错性,每个I帧前面都传一遍 SPS和PPS** 126 | 127 | 128 | 3. NALU playeload : 帧、承载的数据 129 | > 如果 类型是 SPS或者 PPS, playload 是参数集 130 | > 如果类型是 帧; palylaod 是真正的 视频数据, 每个 NALU 存放一片 131 | 132 | 133 | **一个视频,拆分成一系列的额帧,每一帧拆分成一系列的片,每一片放在 NALU里面,NALU 之间通过标识符分割, I帧前面插入 SPS和PPS 、,最终形成 NALU 序列** 134 | 135 | 136 | ------ 137 | 138 | #### 2. 推流 139 | 140 | > 二进制流需要打包成网络包才能发送 --- RTMP 协议 141 | 142 | 143 | * RTMP 基于 TCP ,双方建立一个TCP连接,之后再建立一个 RTMP 连接 144 | > RTMP 建立连接之后 确定 **版本号**和 **时间戳** 145 | 146 | * 客户端发送 C0 ,C1,C2; 服务器发送 S0, S1, S2 147 | 148 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/szq7h.jpg) 149 | 150 | 1. 客户端 C0 表示自己的版本号,了 不等回复直接发送 C1 表示自己的时间戳 151 | 152 | 2. 服务器收到 C0 后回复 S0 表明自己版本号,接着发送 S1 表明时间戳 153 | 154 | 3. C2 是客户端对服务器 发送时间戳的一个回复 ACK ,同理 S2 155 | 156 | ---- 157 | 158 | * 传输数据的时候: 创建一个流 Stream,通过他进行 推流 159 | > 将 NALU 放入 Message 里面发送 --- **RTMP Packet包** 160 | 161 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/5fsct.jpg) 162 | 163 | 164 | * RTMP 收发数据不是以 Message 拆分成 Chunk 发送; 在一个 CHunk发送完 才能发送下一个, 165 | > Chunk 里面有 Message ID,表示属于哪个 Message 便于组装 166 | > 这样将大的消息变为小的,在低带宽的情况下,减少网络拥塞 167 | 168 | 169 | **整个过程** 170 | 171 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ycs6j.jpg) 172 | 173 | --- 174 | 175 | 176 | #### 3. 分发网络 177 | 178 | > 观众可以通过 RTMP 协议从流媒体服务器上拉去视频,但是,都去同一个地方拉去,服务器压力大,时延长,需要分发网络 179 | 180 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/09eyi.jpg) 181 | 182 | * 分为 中心和边缘两层 183 | > 边缘层服务器部署在全国各地,横跨各大运营商。中心层是流媒体服务集群,负责内容的转发 184 | 185 | * 根据用户的地理位置信息,就近选择边缘服务器 186 | 187 | * 中心服务器可以进行转码的工作 188 | 189 | ---- 190 | 191 | #### 4. 拉流 --- 观众通过客户端观看 192 | 193 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/lynmr.jpg) 194 | 195 | * 客户端 将收到的 NALU 组成一个个帧,进行解码,播放器播放 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-物理层和MAC层.md: -------------------------------------------------------------------------------- 1 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 2 | 3 | 4 | ## 1. 物理层基本概念 5 | 6 | 物理层考虑的是如何在连接各种计算机的传输媒体上传输数据比特流,不是具体的传输媒体。 7 | 8 | 9 | 物理层的主要任务是 : 确定与传输媒体接口的一些特性。 10 | 11 | 12 | 13 | 14 | ### 1. 物理层下面的传输媒体: 15 | 16 | 传输媒体 : 数据传输系统中发送器和接收器之间的物理通路 17 | 18 | 19 | 1. 导引型传输媒体 : 电磁波沿着固体媒体传播 (光纤或者双绞线) 20 | 21 | 22 | 23 | 2. 非导引型传输媒体: 电磁波无线传输 (微波通信) 24 | 25 | 26 | 27 | ### 2. 数据通信模型 28 | 29 | 30 | ![](https://i.loli.net/2019/10/01/k5cf8d3lbqmjsvw.jpg) 31 | 32 | 数据通信系统主要包含 : 源系统,传输系统和目的系统 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ## 2. 数据链路层 42 | 43 | ### 1. 基本概念 : 44 | 45 | 46 | #### 1. 数据链路 : 47 | 48 | * 链路是指结点到相邻结点的一段物理线路 49 | 50 | * 数据链路 : 物理链路上面的一些必要的通信协议 51 | 52 | 53 | #### 2. 数据链路层的协议单元 --- 帧 54 | 55 | 需要把网络层传下来的数据构成帧发送到物理层,也要把来自物理层的帧中的数据去处交给网络层。 56 | 57 | 网络层的数据称为 IP 数据报,对数据报加入首部和尾部即封装为 帧 58 | 59 | 60 | #### 3. 三个基本问题: 61 | 62 | 63 | 1. 封装成帧 64 | 65 | 66 | 67 | 2. 透明传输 68 | 69 | 70 | 71 | 3. 差错检测 72 | 73 | 74 | 75 | ### 2. 点对点传输协议 : PPP 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | ### 3. 广播信道 : 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | --- 99 | 100 | 101 | 102 | ## 2. 搭建一个局域网 103 | 104 | 局域网虽然是一个网络, 但是并不放在网络层, 因为网络层主要是将分组从一个网络通过路由器转发到另一个网络。 同一个局域网主要研究从一个主机传送到另一个主机,不经过路由器。主要是数据链路层。 105 | 106 | 107 | 108 | ### 物理层 -- 第一层 109 | 110 | #### 1. 两个电脑 建局域网 --- LAN 111 | 112 | 113 | * 一个网线,连接两个电脑的网卡,实现一端发送信号,另一端可以接收到。 114 | 115 | * 配置两台电脑的 IP 地址,子网掩码和默认网关, 这三项配置称为一个网络 116 | 117 | * IP 层需要封装了 MAC 层才能将包放入物理层 118 | 119 | 120 | 121 | #### 2. 多个电脑 HUB 集线器 122 | 123 | * 集线器完全在物理层工作,将收到的每个字节,都复制到其他的端口 124 | 125 | 126 | ---- 127 | 128 | ### 数据链路层 -- 第二层 129 | 130 | > 由于 HUB 采取的是广播模式,如果一台电脑发出的包,其他的电脑都能接受到,就会出现问题 131 | 132 | 133 | ##### MAC 媒体访问控制 : 控制在发送数据的时候, 先后的问题 ------ 多路访问 134 | > 以太网使用的解决方式 : 随机接入协--- 有事就出门, 遇到高峰就回去,错过高峰再出 135 | 136 | 137 | 138 | 139 | ##### MAC 地址(链路层地址); 解决 发给谁,接收的问题 140 | 141 | 142 | 1. 第二层的网络包格式: 目标的 MAC。和 原的 MAC 地址 143 | 144 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/h0k9n.jpg) 145 | 146 | 2. 网络包类型 : IP 数据包(TCP, UDP 以及 HTTP 等) 147 | 148 | 3. MAC 接收 :数据包在链路上广播, MAC 网卡 发现接收, 打开 IP 包,发现 IP 地址也是自己的,再打开 TCP ,发现端口也是自己的。 149 | 150 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/zqsww.jpg) 151 | 152 | 4. 将 请求提交到 nginx,nginx 返回一个网页。再将网页需要发回请求的机器。 层层封装 最后到 MAC 层 153 | 154 | 155 | 156 | ##### CRC (循环冗余检查) : 解决发送错误 157 | > 通过 XOR异或 算法,计算整个包是否在发送的过程中出现了错误 158 | 159 | 160 | ##### ARP 协议 : 解决 MAC 未知的问题 161 | 162 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/i97ys.jpg) 163 | 164 | > 在同一个局域网里面, 查看 ARP 表, 查不到就 广播 ARP 请求,对应的机器做回答 165 | > 为了避免每次都用 ARP 请求, 机器本地 进行 ARP 缓存 IP- MAC的映射列表 166 | 167 | 168 | ---- 169 | 170 | ### Hub -> 交换机 171 | 172 | * Hub 是广播的, 所有的Bit 都会发送到接口, 由主机来判断是不是需要。 173 | 174 | * 交换机, 通过学习记住每个 MAC 值对应的接口,以后有包的目的地址是相应的 MAC 直接发送到对应的口 175 | > 但是 机器的 IP 地址会发生变化,交换机学习的结果,时效有限 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-网关.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | > 除了 在宿舍和办公室的局域网, 还有外网 7 | 8 | ### 宿舍上网 9 | 10 | > 宿舍给每个网口分配一个 IP地址,校园网的 IP;10.10.x.x 宿舍网 有个 IP地址 : 192.168.1.x 11 | 12 | * 路由器的外网网口插到校园网网口上, 外网网口配置成和网管部门一样; 内网网口连接宿舍的所有电脑 13 | 14 | * 接下来需要网卡配置 : IP地址由 DHCP 默认配置; 还需要 **Gateway** 配置 15 | 16 | 17 | ----- 18 | 19 | ### 跨网关访问 的 MAC 头 和 IP 头 20 | 21 | 22 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/bupdl.jpg) 23 | 24 | * MAC 头中的协议类型,用来说明里面是 IP协议 25 | 26 | * IP 头 里面的版本 是 IPV4 或者 IPV6 27 | 28 | * 服务类型 Type of Sevice : TOS 代表了当前包的优先级; 29 | 30 | * TTL 31 | 32 | * 8 位协议 : 是 TCP or UDP 33 | 34 | ----- 35 | 36 | ### 判断是否是同一个网段 37 | 38 | > 需要 CIDR 和子网掩码 39 | 40 | * 如果是同一个网段 41 | > 将源地址和目标地址放入IP头中, 然后通过 ARP 获得 MAC ,将源MAC 和目的 MAC 放入 MAC 头中; 发出。 42 | 43 | * 如果不是同一网段 44 | 45 | 1. 需要发往默认网关 Gateway 。 Gateway 的地址一定是和 源 IP 是一个网段的。 46 | > 例如 192.168.1.0/24 这个网段,Gateway 往往会是 192.168.1.1/24 或者 192.168.1.2/24。 47 | 48 | 2. 由于网关和源 IP 地址是同一个网段的,过程类似于发往同一个网段 -- 通过 ARP 获得网关的MAC 地址,将源MAC 和网关 的MAC 放入 MAC 头 49 | 50 | 3. 网关所在的端口将网络包收入, 拿下MAC头和IP头,选择另一个网关,加上 IP头和MAC头 发送 51 | 52 | ---- 53 | 54 | ### 静态路由 55 | 56 | > 在 路由器上配置一条条的规则; 例如想访问 BBS 站,从2号口出去,下一跳 是 IP2 57 | 58 | ---- 59 | 60 | ### IP 地址不变 61 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ojfd1.jpg) 62 | 63 | > 服务器A 访问 服务器 B; 不在同一个网段 64 | 65 | 1. A 将包发送到网关 ; 包中有: 66 | * 源 MAC : 服务器A 的 MAC 67 | * 目标 MAC : 网关的 MAC 68 | * 源 IP : 服务器 A 的IP地址、 69 | * 目标 IP : 服务器B 的地址 70 | 71 | 72 | 2. 路由器 A 中配置了静态路由, 知道从 92.168.56.1 这个口出去,下一跳为 192.168.56.2 73 | > 下一跳 : 某个 IP 要将这个 IP 地址转换为 MAC 放入 MAC头 74 | 75 | 76 | 77 | 3. 获取 192.168.56.2 的 MAC 地址,打包发送,IP 不变 78 | 79 | 4. 路由器B中配置了静态路由, 从 192.168.4.1 这个口出去,没有下一跳,获取 服务器B的 MAC地址 发送包 80 | 81 | ----- 82 | 83 | ### IP 地址改变 84 | 85 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/5vki4.jpg) 86 | 87 | > 局域网的 IP 段冲突了 88 | 89 | 1. 目标服务器的 IP 转换, 192.168.1.101 对应 192.168.56.2 90 | 91 | 2. 服务器 A 访问 目标服务器 B 指定的目标地址 192.168.56.2 92 | 93 | 3. 其他的 程序类似于上一个,直到 包到达 路由器B 94 | 95 | 4. 路由器 B 是一个 NAT 网关,它上面配置了,192.168.1.101 对应 192.168.56.2,改为访问 192.168.1.101 96 | > NAT :Network Address Translation,简称NAT 97 | 98 | 5. 从路由器 B 的192.168.1.1 这个口发出 发给192.168.1.101 ; 源 IP : 192.168.56.1 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-路由协议.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | ---- 5 | 6 | **出了网关,会有很多路由器,如何选择** 7 | 8 | 9 | ### 路由器配置--- 路由表 10 | 11 | > 网络包传入到路由器,根据本地的转发信息库,决定正确的转发流量 --- 路由表 12 | 13 | * 每个路由表有很多路由规则,每条规则包含 14 | 15 | 1. 目的网络 16 | 17 | 2. 出口设备: 从哪个口扔包 18 | 19 | 3. 下一跳网关 : 下一个路由器的地址 20 | 21 | 22 | **使用 route 命令和 ip route 命令进行查询配置** 23 | 24 | ```python 25 | $ ip route add 10.176.48.0/20 via 10.173.32.1 dev eth0 26 | # 要去 10.176.48.0 这个目标网络,从 eth0出去, 经过 10.173.32.1 27 | 28 | ``` 29 | 30 | ----- 31 | 32 | ### 配置策略路由 33 | 34 | * 配置多个路由表; 根据 IP 地址 入口设备 等选择 路由表 35 | 36 | ```python 37 | $ ip rule add from 192.168.1.0/24 table 10 # 从这个网段来的 使用table 10 中的路由表 38 | $ ip rule add from 192.168.2.0/24 table 20 39 | 40 | ``` 41 | 42 | 43 | ---- 44 | 45 | ### 动态路由算法 46 | 47 | 48 | > 上面的是静态的路由, 网络环境复杂多变,修改复杂 49 | 50 | > 动态路由器,根据协议算法生成动态路由表,随着网络运行状况的变化而变化 51 | 52 | **寻找最短路径的问题** 53 | 54 | 55 | 56 | ##### 距离矢量路由法 --- Bellman-Ford 57 | 58 | 59 | 60 | ##### 链路状态路由法 --- Dijkstra 61 | 62 | * 每个路由器启动的时候获取和自己邻居的距离,并将链路状态发送到整个网络 63 | 64 | * 每个路由器都能够在本地构建一个完整的图, 使用 Dijkstra算法,寻找最短路径 65 | 66 | * 更新的时候,只广播更新的或者改变的网络拓扑 67 | 68 | 69 | 70 | 71 | ---- 72 | 73 | ### 动态路由协议 74 | 75 | ##### 基于链路状态路由算法的 OSPF 76 | 77 | * 广泛应用于数据中心的内部,用于路由决策----成为**内部网关协议** IGP 78 | 79 | 80 | * OSPF 可以发现多个最短的路径,在多个路径中进行负载均衡 --- 等价路由 81 | 82 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/3to8r.jpg) 83 | 84 | 85 | > 等价路由,可以分摊流量; 当一条路不同的时候走另一条路 86 | 87 | ##### 基于距离矢量路由算法的 BGP 88 | 89 | > 外网的路由协议 90 | 91 | * 每个数据中心都有自己的 Policy, 92 | > 哪些可以通过,哪些不能通过 93 | 94 | * 网络世界里面,存在着自治系统, Autonomous System 95 | 96 | * Stub AS:对外只有一个连接, 不会传输其他 As 的包 : 个人或者小公司 97 | * Multihomed AS:可能有多个连接连到其他的 AS ,大多拒绝为其他的AS传输包 : 大公司 98 | * Transit AS:有多个连接连到其他的 AS, 并且可以帮助其他的 AS传输包, 例如主干网 99 | 100 | 101 | 102 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/1s0xq.jpg) 103 | 104 | * 1. eBGP : 自治系统的边界路由器之间使用eBGP 广播路由 105 | 106 | * 2. iBGP : 内部的路由器找到达到外网目的地的边界路由器; 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /Network_protocol/网络协议-配置IP地址.md: -------------------------------------------------------------------------------- 1 | 2 | * 本文主要内容为**刘超**老师在极客时间上的《趣谈网络协议》课程学习笔记 3 | 4 | --- 5 | 6 | ### 配置 IP 地址 7 | 8 | * Net - tools 9 | ``` 10 | $ sudo ifconfig eth1 10.0.0.1/24 11 | $ sudo ifconfig eth1 up 12 | 13 | ``` 14 | 15 | 16 | ### 动态主机配置协议 --- DHCP 17 | 18 | > 数据中心的服务器, IP 一旦配置号,基本不会改变,相当于买房自己装修; DHCP 相当于租房, 暂时使用,用完退租。 19 | 20 | 21 | #### DHCP Discover 22 | 23 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/lewx6.jpg) 24 | 25 | * 一台机器加入一个新的网络,只有自己的 MAC 地址, 使用 IP 0.0.0.0 发送一个广播包 到目的 IP : 255.255.255.255 26 | 27 | * 广播包 封装了 UDP, UDP封装了 BOOTP (DHCP 是BOOTP 的增强版) 28 | 29 | * 信任度 会。Boot request ,---- 我的 MAC是 。。。 我还没有 IP , 租给我个 IP 30 | 31 | 32 | #### DHCP Server 33 | 34 | * 网络里面配置了 DHCP Server, 相当于 IP 的管理者, 能够知道有 “新人” 进来 --- MAC 的唯一性 35 | 36 | 37 | #### DHCP Offer 38 | 39 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/pmcmu.jpg) 40 | 41 | * 租借给新人一个 IP 地址 42 | 43 | * 同时,为 新人保留这个 IP 地址, 从而不会提供给别人 44 | 45 | * DHCP Server 使用 广播地址作为目的地址,因为 新人还没有自己的 IP 46 | 47 | * 服务器 同时发送, 子网掩码, 网关, IP 地址租用期限 等信息 48 | 49 | 50 | 51 | #### DHCP Request 52 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/6anl4.jpg) 53 | 54 | * 如果有 多个 DHCP Server ,新人会收到 多个 IP 地址, 会选择一个,一般是最先到达的那个 55 | 56 | * 之后向网络发送一个 DHCP Request 的广播数据包, 包括: MAC 地址, 接受的 IP 地址, 提供 IP 的 DHCP 服务器地址, 并告诉其他的 DHCP 服务器,撤销 提供的 IP 地址,以便提供给下一个 57 | 58 | * 由于还没有 DHCP Server 的确认, IP地址 仍然不变 59 | 60 | #### DCHO ACK 61 | 62 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/c5orq.jpg) 63 | 64 | * DHCP Server 接收到 request 后, 广播返回一个 ACK 的消息包, 包扩: IP 的配置信息等 65 | 66 | 67 | 68 | #### IP 的 收回和续租 69 | 70 | * 客户机在 租期 50% 的时候发送 DHCP Request , 服务器将返回ACK 消息包, 包含新的租期以及其他的 TCP/IP 参数 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Python/ 写代码时如何创建有意义的名称.md: -------------------------------------------------------------------------------- 1 | 原文链接🔗 --- How To Create Meaningful Names In Code 2 | 3 | https://medium.com/better-programming/how-to-create-meaningful-names-in-code-20d7476537d4 4 | 5 | ---- 6 | 7 | 8 | 写代码的时候需要考虑命名 files , classes , methods, and variables 等 9 | 10 | 11 | 需要一些简单的规则,以便于更好的创建好的名字 12 | 13 | 14 | 15 | 16 | ## 1. 名字能够反映 意图 17 | 18 | 一个好的经验法则是: 如果名字需要注释, 那么这个名字没有显示意图 19 | 20 | 21 | ```python 22 | 23 | s ### time in seconds 24 | 25 | 26 | ####### 27 | 28 | 29 | seconds_since_last_modified 30 | 31 | 32 | ``` 33 | 34 | 35 | 下面的变量名字明显比上面的更容易理解是什么, 虽然起名字可能花费更多的时间,但是有助于理解代码 36 | 37 | 38 | 39 | ```python 40 | def get_list(the_list): 41 | list_1 = [] 42 | 43 | for i in the_list : 44 | if i % 2 != 0: 45 | list_1.append(i) 46 | 47 | return list_1 48 | 49 | 50 | ############ 51 | 52 | def get_odd_numbers(the_list): 53 | odd_numbers_list = [] 54 | 55 | for number in the_list : 56 | if number % 2 !=0 : 57 | odd_numbers_list.append(number) 58 | 59 | return odd_numbers_list 60 | 61 | 62 | 63 | 64 | ``` 65 | 66 | 67 | 68 | * 下面的函数 因为命名上的改变, 明显相较于上面的代码 更加容易理解 69 | 70 | 71 | ---- 72 | 73 | 74 | ## 2. 避免虚假信息 75 | 76 | 77 | 1. 避免误导性的词语: 78 | 79 | 例如 使用 **productslist** 命名 一组产品, 会使人误认为这个变量的类型是 列表(除非他真的是列表) 80 | 81 | 82 | 2. 避免 **O 和 l** 因为 和 0,1 太相似了 83 | 84 | 85 | 3. 避免使用 变化很小的名字 86 | ‘’SomeMethodForEfficientHandlingOfFile‘’ 和 ‘’SomeMethodForEfficientStorageOfFiles‘’ 87 | 88 | 很难进行区分 89 | 90 | --- 91 | 92 | ## 3. 进行有意义的区别 93 | 94 | 使用 数字序列命名 不是一个好的命名方式 95 | 96 | ```python 97 | def duplicate_dict(dict1,dict2): 98 | for key, value in dict1.items(): 99 | dict2[key] = value 100 | 101 | return dict2 102 | 103 | ``` 104 | 105 | dict1,dict2 没有反应很多的信息 106 | 107 | 108 | ```python 109 | 110 | def duplicate_dict(source,destination): 111 | for key, value in source.items(): 112 | destination[key] = value 113 | 114 | return destination 115 | 116 | ``` 117 | 118 | 119 | 同样的代码, 改成 source ,destination, 函数复制功能更加清晰 120 | 121 | 122 | ----- 123 | 124 | 125 | ## 4. 使用 可以拼写,读出来的 名字 126 | 127 | 128 | 在讨论代码的时候, 变量名称不可读, 或者很难读 129 | 130 | 例如 xsq = 1 131 | 132 | 就会 很难沟通 133 | 134 | 135 | ---- 136 | 137 | 138 | ## 5. 使用可搜索的名字 139 | 140 | 使用 单字母命名名字存在一个问题就是 , 很难在代码中找到 141 | 142 | 除非这个变量只存在一个较短的 methods 里面 143 | 144 | 145 | ---- 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Python/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Python/.DS_Store -------------------------------------------------------------------------------- /Python/Python 函数中的 -> 是什么意思.md: -------------------------------------------------------------------------------- 1 | 2 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/axt54.JPG) 3 | 4 | --- 5 | 6 | 搬运自 https://stackoverflow.com/questions/14379753/what-does-mean-in-python-function-definitions 7 | 8 | ----- 9 | 10 | ## 1. 函数的注释 11 | 12 | 类似于 Python2 中的 docstrings,python3 中用来描述函数的参数和 return values 13 | 14 | 例如: 15 | 1. 用来声明参数的 type 16 | 2. Another is to allow parameter-specific documentation instead of encoding it into the docstring. 17 | 3. python 解释器不会对注解添加任何的语意,运行和没有添加注释时候一样 18 | 19 | 20 | ## 2. Example 21 | 22 | 1. 如下面的函数,是一个简单的动能定理公式, 23 | 输入的有 m 质量; 速度 v 24 | 返回的是能量 e 单位是焦耳 Joules 25 | 26 | ```python 27 | def kinetic_energy(m:'in KG', v:'in M/S')->'Joules': 28 | ... return 1/2*m*v**2 29 | 30 | 31 | ``` 32 | 33 | 2. 我们可以使用 .__annotations__ 调用 注释信息 34 | 35 | 36 | ```python 37 | 38 | kinetic_energy.__annotations__ 39 | Out[2]: {'m': 'in KG', 'v': 'in M/S', 'return': 'Joules'} 40 | 41 | ``` 42 | 43 | 3. .__annotations__ 返回的类型是 Dictionary ,使用 key 可以调用结果 44 | 45 | ```python 46 | 47 | kinetic_energy.__annotations__['return'] 48 | Out[3]: 'Joules' 49 | 50 | kinetic_energy.__annotations__['v'] 51 | Out[4]: 'in M/S' 52 | ``` 53 | 54 | 4. 我们可以在添加注释的时候,就直接添加一个字典结构的注释 55 | 56 | ```python 57 | 58 | rd={'type':float,'units':'Joules','docstring':'Given mass and velocity returns kinetic energy in Joules'} 59 | 60 | def f()->rd: 61 | pass 62 | f.__annotations__['return']['docstring'] 63 | Out[8]: 'Given mass and velocity returns kinetic energy in Joules' 64 | 65 | f.__annotations__['return']['units'] ## 双重字典嵌套 66 | Out[9]: 'Joules' 67 | 68 | ``` 69 | 70 | 71 | ## 3. Future : 72 | 73 | > The fastest conceivable scheme would introduce silent deprecation of non-type-hint annotations in 3.6, full deprecation in 3.7, and declare type hints as the only allowed use of annotations in Python 3.8. 74 | 75 | 在未来的版本中 -> 可能只能用来 说明返回的 类型 Type 76 | 77 | ```python 78 | def f(x) -> int: 79 | return x 80 | ``` 81 | 82 | 83 | 而不能是 84 | 85 | ```python 86 | 87 | def f(x) -> 123: 88 | return x 89 | 90 | ``` 91 | 92 | ----- 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /Python/Python3.8 有用的新特性.md: -------------------------------------------------------------------------------- 1 | 原文: Awesome New Python 3.8 Features 2 | 3 | link : https://medium.com/fintechexplained/awesome-new-python-3-8-features-ed027416f2a5 4 | 5 | ----- 6 | 7 | 8 | ## 1. 赋值表达式 **:=** 9 | 10 | * 将值赋值给未初始化的变量 11 | 12 | ```python 13 | if (my_variable := get_input()) is not None : 14 | print(my_variable) #exists now 15 | ``` 16 | 17 | my_variable 没有提前初始化, **:=** 用来声明和初始化 my_variable。 18 | get_input()函数的返回值用来给变量赋值。 19 | 20 | **This feature is available in list comprehensions and statement forms.** 21 | 22 | * 确保变量的赋值在圆括号内 23 | ```python 24 | my_variable := get_input() #Invalid 25 | ``` 26 | 27 | * = 和 := 之间 逗号的优先级不同 28 | 29 | ```python 30 | my_variable = a, b, c # my_variable = (a, b, c) 31 | (my_variable := a, b, c) # my_variable = a 32 | ``` 33 | 34 | 35 | ---- 36 | 37 | ## 2. 限制必须按照位置传递参数 38 | 39 | * 使用 "/" 40 | 41 | ```python 42 | def add(a, b, c, d=None, /): 43 | x = a+b+c 44 | if d is not None: 45 | x = x+d 46 | return x 47 | ``` 48 | 49 | * add(a=1,b=2,c=3) or add(1,2,3,d=4) 都是无效的调用 50 | 51 | * add(1,2,3) and add(1,2,3,4) 是有效的 52 | 53 | 这个功能看起来没什么用。 54 | 使用位置函数,API编写器可以重命名函数的参数(如果需要),而不破坏API调用者的代码。因此,它鼓励API向后兼容。 55 | 56 | ---- 57 | 58 | ## 3. f-strings 支持 = 59 | 60 | * f'{expr = }' 61 | 62 | = 实际上是对表达式求值然后输出结果 63 | 64 | ```python 65 | input = 100 66 | output = 50 67 | print(f'{input-output=}') 68 | ``` 69 | 70 | 输出结果是: **input-output=50** 71 | 72 | ---- 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | ---- 91 | 92 | # 参考 93 | 94 | 1. [PEP 572 -- Assignment Expressions](https://www.python.org/dev/peps/pep-0572/) -------------------------------------------------------------------------------- /Python/python 垃圾回收机制.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《 python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 图灵机架构 6 | 7 | 1. 图灵机架构的本质是无限长的纸袋, 相当于 存储器, 之后HU年间完善出现 寄存器, 易失性存储器(内存) 和 永久性储存器(硬盘) , 8 | 9 | 2. Python 程序运行的时候, 需要 内存开辟空间,用于运行时候产生的临时变量, 计算完成, 再将结果储存到磁盘。 10 | 11 | 3. 数据量过大, 内存可能不足, 内存管理不好,导致内存泄漏 12 | 13 | * 内存泄漏指的是 程序未能释放已经不再使用的内存 14 | 15 | * 分配了某段内存之后,因为设计失误,失去了对内存的控制,造成内存的浪费 16 | 17 | 18 | --- 19 | 20 | ## 2. 计数引用 21 | 22 | Python 中创建的实例 的都会有一个引用计数,来记录由多少个指针指向实例,当引用计数为 0 的时候,自动释放内存。 23 | 24 | 25 | 1. 垃圾回收 26 | 27 | ```python 28 | 29 | import os 30 | import psutil 31 | 32 | 33 | def show_memory(hint): 34 | pid = os.getpid() 35 | p = psutil.Process(pid) 36 | 37 | info = p.memory_full_info() 38 | memory = info.uss/1024./1024 39 | print("{} memory used : {} MB ".format(hint,memory)) 40 | 41 | 42 | def func(): 43 | show_memory("initial") 44 | a = [i for i in range(10000000)] 45 | show_memory("after processing") 46 | 47 | func() 48 | show_memory("finished") 49 | 50 | ############ 51 | 52 | initial memory used : 78.33984375 MB 53 | after processing memory used : 465.3359375 MB 54 | finished memory used : 82.0703125 MB 55 | 56 | ``` 57 | 58 | * 函数内部声明的变量是 局部变量, 函数返回之后, 局部变量的引用会被注销掉, 声明的列表就会被执行垃圾回收, 收回占用的内存 59 | 60 | 61 | 2. 62 | 63 | 64 | ```python 65 | 66 | import os 67 | import psutil 68 | 69 | 70 | def show_memory(hint): 71 | pid = os.getpid() 72 | p = psutil.Process(pid) 73 | 74 | info = p.memory_full_info() 75 | memory = info.uss/1024./1024 76 | print("{} memory used : {} MB ".format(hint,memory)) 77 | 78 | 79 | 80 | def func(): 81 | show_memory("initial") 82 | global a 83 | a = [i for i in range(10000000)] 84 | show_memory("after processing") 85 | 86 | 87 | func() 88 | show_memory("finished") 89 | 90 | 91 | ######### 92 | 93 | initial memory used : 81.48828125 MB 94 | after processing memory used : 453.5078125 MB 95 | finished memory used : 453.51171875 MB 96 | 97 | 98 | ``` 99 | 100 | * 因为 a 声明的是全局变量, 函数返回之后, 列表的引用依然存在,对象不会被垃圾回收,依然占据大量的内存 101 | 102 | 103 | 104 | 105 | 106 | 3. 107 | 108 | ```python 109 | 110 | def func(): 111 | show_memory("initial") 112 | a = [i for i in range(10000000)] 113 | show_memory("after processing") 114 | return a 115 | 116 | a = func() 117 | show_memory("finished") 118 | 119 | ############# 120 | 121 | initial memory used : 454.28125 MB 122 | after processing memory used : 768.890625 MB 123 | finished memory used : 768.890625 MB 124 | 125 | ``` 126 | 127 | 128 | 4. 引用计数机制 129 | 130 | 131 | * 函数调用的时候, 会产生两次引用, 一次来自函数栈 ,里一个来自函数参数 132 | 133 | * 函数统计的是引用的次数, 而不是指针 134 | 135 | 136 | --- 137 | 138 | ## 3. 手动释放内存 139 | 140 | 141 | 接着上面的 内存占用 768 142 | 143 | ```python 144 | del a 145 | 146 | import gc 147 | gc.collect() 148 | 149 | show_memory("finished") 150 | 151 | ######## 152 | 153 | gc.collect() 返回 清除掉的垃圾变量的个数。 154 | 155 | finished memory used : 78.22265625 MB 156 | 157 | ``` 158 | 159 | --- 160 | 161 | ## 4. 循环引用 162 | 163 | 1. 如果两个对象互相引用, 没有别的对象引用, 是否应该被垃圾回收 164 | 165 | 166 | ```python 167 | 168 | def func(): 169 | show_memory("initial") 170 | a = [i for i in range(10000000)] 171 | b = [i for i in range(10000000)] 172 | show_memory("after created") 173 | a.append(b) 174 | b.append(a) 175 | 176 | func() 177 | show_memory("finished") 178 | 179 | ########### 180 | 181 | initial memory used : 77.90234375 MB 182 | after created memory used : 850.109375 MB 183 | finished memory used : 850.109375 MB 184 | 185 | ``` 186 | 187 | 我们可以发现, 因为互相引用, 导致 a,b 引用数都不为 0 188 | 189 | 重复调用 函数的话,内存占用会越来越大, 190 | 191 | ``` 192 | initial memory used : 760.92578125 MB 193 | after created memory used : 1025.984375 MB 194 | finished memory used : 1025.984375 MB 195 | 196 | ``` 197 | 198 | 199 | 2. 显示调用 gc.collect() 200 | 201 | ```python 202 | 203 | gc.collect() 204 | 205 | show_memory("finished") 206 | 207 | ######## 结果######### 208 | 184 209 | finished memory used : 82.5234375 MB 210 | 211 | ``` 212 | 213 | **可以看到 垃圾回收机制对于循环引用,也可以很好的回收** 214 | 215 | 216 | 217 | --- 218 | 219 | ## 4. Python 垃圾回收机制 220 | 221 | 标记清除 和 分代收集 222 | 223 | 1. 标记清除: 224 | 225 | 对于一个 有向图,如果从一个节点出发进行遍历, 标记其经历过的节点, 没有被标记的节点,就是不可达节点。 226 | 这些节点的存在没有意义, 需要对其进行垃圾回收 227 | 228 | 229 | 2. 分代收集算法 230 | 231 | Python 将所有的对象分为三代, 刚刚创立的对象是 0 代, 经过一次垃圾回收之后,依然存在的对象,便会从上一代移动的下一代。 232 | 233 | 每一代启动自动垃圾回收的阈值 都是可以单独制定的, 234 | 235 | 新生的对象更有可能被垃圾回收; 存活更久的对象更高的概率存活 236 | 237 | --- 238 | 239 | 240 | 241 | ## 5. 调试 内存泄漏 242 | 243 | 使用 objgraph --- 可视化引用关系 244 | 245 | 246 | 1. show_refs() : 生成引用关系图 247 | 248 | ```python 249 | import objgraph 250 | 251 | a = [1,2,3] 252 | 253 | b = [4,5,6] 254 | 255 | a.append(b) 256 | b.append(a) 257 | 258 | 259 | objgraph.show_refs([a]) 260 | 261 | ``` 262 | 263 | ![](https://i.loli.net/2019/07/18/5d3074f8403a741426.png) 264 | 265 | 直观的看到互相引用 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | -------------------------------------------------------------------------------- /Python/python 中匿名函数 lambda.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 匿名函数的基础 6 | 7 | 匿名函数的格式 8 | 9 | ```python 10 | lambda argument1, argument2,... argumentN : expression 11 | 12 | ``` 13 | 14 | ```python 15 | 16 | square = lambda x : x**2 17 | 18 | >>> square(3) 19 | 9 20 | 21 | ``` 22 | 23 | * 匿名函数和常规函数一样,返回的都是一个函数对象 24 | 25 | * lambda 可以用在列表内部 -- 常规函数不能 26 | 27 | ```python 28 | 29 | [(lambda x : x*x)(x) for x in range(10)] 30 | 31 | 32 | [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 33 | 34 | ``` 35 | 36 | * lambda 可以用作某些函数的参数 37 | 38 | 39 | ```python 40 | 41 | l = [(1, 20), (3, 0), (9, 10), (2, -1)] 42 | l.sort(key=lambda x: x[1]) # 按列表中元祖的第二个元素排序 43 | 44 | >>> l 45 | [(2, -1), (3, 0), (9, 10), (1, 20)] 46 | 47 | ``` 48 | 49 | 50 | 51 | * lambda 适用于简短 不重复调用的 52 | 53 | 54 | ```python 55 | 56 | squared = map(lambda x : x*x , [1,2,3,4,5]) 57 | 58 | ``` 59 | 对列表中所有的元素平方 60 | 61 | 62 | 63 | 64 | 65 | ---- 66 | 67 | 68 | ## 2. Python 函数式编程 69 | 70 | 71 | 代码中的每一块都是不可变的, 都是由纯函数的形式组成 72 | 73 | 纯函数: 本身相互独立, 相同的输入,有相同的输出 74 | 75 | 优点: 76 | 77 | * 程序更加健壮 78 | 79 | * 易于调试和测试 80 | 81 | 82 | ## 3. 函数式编程接口 83 | 84 | 85 | 1. map() 函数, 之前介绍过 86 | 87 | 函数直接由 c语言写成吗内部做了诸多优化, 运行速度快 88 | 89 | 2. filter(function, iterable) 90 | 91 | filter 对于后面迭代的元素,都使用函数进行判断, 返回 True 或者 False 92 | 返回 True的元素组成一个新的集合 93 | 94 | ```python 95 | 96 | l = [1,2,3,4,5,6,7,8] 97 | 98 | new_list = filter(lambda x: x%2 == 0, l) 99 | 100 | 101 | >>> new_list 102 | 103 | 104 | >>> print(new_list) 105 | 106 | >>> print(list(new_list)) ## 注意 加入 list() 107 | [2, 4, 6, 8] 108 | 109 | ``` 110 | 111 | 112 | 3. reduce(function, iterable) 113 | 114 | 累积的操作 : 对于 iterable 的每个元素以及上一次的结果 使用 function (两个参数) 115 | 116 | ```python 117 | 118 | from functools import reduce 119 | 120 | l = [1, 2, 3, 4, 5] 121 | 122 | result = reduce(lambda x, y: x *y , l) 123 | ``` 124 | 125 | 126 | 127 | 128 | --- 129 | 130 | ## 4. 例子 131 | 132 | ```python 133 | d = {'mike': 10, 'lucy': 2, 'ben': 30} 134 | 135 | ``` 136 | 根据值 由高到低排 137 | 138 | 139 | ```python 140 | sorted(d.items(), key = lambda x : x[1], reverse = True) 141 | 142 | 143 | [('ben', 30), ('mike', 10), ('lucy', 2)] 144 | ``` 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /Python/python 中字典和集合.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | 6 | ## 1. 字典和 集合的基础 7 | 8 | 1. Python 3.7+ 之后 字典呗确定为有序的; 3.6 中是 无法确保其有序性 ;3.6 之前是无需无序的 9 | 10 | 11 | 2. 字典对于查找, 添加和删除等操作,时间复杂度 O(1) 12 | 13 | 3. 集合和字典的区别在于 : 集合没有 key 和 value 的配对,是一系列无序的唯一的元素集合 14 | 15 | 16 | 4. 字典和集合的创建 17 | 18 | 19 | ```python 20 | d1 = {"liu":23, "zou": 13} 21 | d2 = dict({"liu": 23,"zou": 13}) 22 | 23 | s1 = {1, 2, 3} 24 | s2 = set([1, 2, 3]) 25 | 26 | ``` 27 | 28 | 5. 元素的访问 29 | 30 | 5-1 字典 31 | 32 | 通过键 索引, 不存在, 抛出异常 33 | 34 | ```python 35 | 36 | >>> d1 = {"liu":23, "zou": 13} 37 | >>> d2 = dict({"liu": 23,"zou": 13}) 38 | >>> d1["liu"] 39 | 23 40 | 41 | >>> d1['chaung'] 42 | Traceback (most recent call last): 43 | File "", line 1, in 44 | KeyError: 'chaung' 45 | 46 | ``` 47 | 48 | 使用 类函数索引, 不存在则可以返回一个默认值 49 | 50 | ```python 51 | >>> d1.get('liu') 52 | 23 53 | >>> d1.get('chuang') 54 | >>> d1.get('chuang','null') 55 | 'null' 56 | 57 | ``` 58 | 59 | 5-2 集合 -- 无序不重复的元素集 60 | 61 | ** 不支持索引操作,集合的本质是 哈希表** 62 | 63 | 支持: 64 | 65 | ```python 66 | 67 | x in set # 判断是否在集合里面 68 | 69 | for x in set: 70 | 71 | len(set) 72 | 73 | ``` 74 | 75 | set 不重复的特性, 用来去除 列表中 海量重复的元素 76 | 77 | ```python 78 | a = [11,22,33,44,11,22] 79 | b = set(a) 80 | a = [i for i in b] 81 | ``` 82 | 83 | 84 | 6. 字典和集合进行排序 85 | 86 | 6-1 字典排序 87 | 88 | 根据 key 或者 根据 value 89 | 90 | ```python 91 | 92 | d = {'b': 1, 'a': 2, 'c': 10} 93 | d_sorted_by_key = sorted(d.items(), key=lambda x: x[0]) # 根据字典键的升序排序 94 | d_sorted_by_value = sorted(d.items(), key=lambda x: x[1]) # 根据字典值的升序排序 95 | 96 | >>> d_sorted_by_key 97 | [('a', 2), ('b', 1), ('c', 10)] 98 | 99 | ``` 100 | 101 | **排序后 返回的是 列表** 102 | 103 | 6-2 集合排序 104 | 105 | ```python 106 | s = {1,3,4,2,6,5} 107 | >>> sorted(s 108 | ... ) 109 | [1, 2, 3, 4, 5, 6] 110 | 111 | 112 | ``` 113 | 114 | **同样返回排序好的列表** 115 | 116 | 117 | ---- 118 | 119 | ## 2. 字典和集合的性能 120 | 121 | 122 | 字典和集合是性能高度优化的数据结构,对于查找,删除添加等操作,时间复杂度是 O(1). 123 | 124 | 字典和集合的内部结构都是一张哈希表 125 | 126 | 字典: 储存了哈希值,键和值 3 个元素。 127 | 集合: 哈希表没有见和值, 只有单一的元素。 128 | 129 | 为了提高储存空间的利用率, 哈希表除了字典本身的结构,将索引和( 哈希值,键,值单独分开) 130 | 131 | ```python 132 | Indices 133 | ---------------------------------------------------- 134 | None | index | None | None | index | None | index ... 135 | ---------------------------------------------------- 136 | 137 | Entries 138 | -------------------- 139 | hash0 key0 value0 140 | --------------------- 141 | hash1 key1 value1 142 | --------------------- 143 | hash2 key2 value2 144 | --------------------- 145 | ... 146 | --------------------- 147 | 148 | 149 | ``` 150 | 151 | 152 | 153 | ### 1. 插入操作 154 | 155 | 1. 向字典插入一个元素, python 计算 键值的 Hash , 156 | 2. 计算 mask = PyDicMinSize - 1 157 | 3. 计算 index = mask & hash 158 | 4. 如果 位置是空的, 插入 159 | 5. 如果位置占用 : 160 | 5-1 : 两个元素的 哈希值和键值都相同,表明元素已经存在, value 不同, 更新value 161 | 5-2 : 两者中有一个不相同, 这种时候出现 哈希冲突, hash collision, python 会继续寻找合适的表中其他的位置 162 | 163 | 164 | ### 2. 查找 165 | 166 | 给定 key 值, 计算相应的 hash ,找到 相应的 value。 167 | 168 | 169 | ### 3. 删除操作 170 | 171 | 暂时对这位置的元素赋予一个特殊的值, 重新调整哈希表的大小的时候, 删除。 172 | 173 | ### 4. 哈希表大小 174 | 175 | 为了避免冲突, 字典内的哈希表,通常会保证留有 1/3 的剩余空间。 176 | 当剩余空间小于 1/3 的时候, Python会重新获取更大的内存空间,扩充哈希表。 177 | 178 | 179 | ### 5. 字典初始化 180 | 181 | ```python 182 | 183 | d = {"liu": 23, "zou ": 13} 184 | 185 | d = dict({"liu": 23, "zou ": 13}) 186 | 187 | 188 | ``` 189 | 190 | 第一种 初始化效率更高, {} 是关键字, 内部直接调用 底层的 C 的代码 191 | 192 | 193 | ### 6. 字典的 key 不能是一个列表 , 可以是元组 194 | 因为列表 是一个动态变化的数据结构, 字典中的 key 是要求不可以变化的 195 | 196 | 197 | 198 | # 参考 199 | 200 | 1. Python集合(set)类型的操作-- https://blog.csdn.net/business122/article/details/7541486 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /Python/python 中字符串.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | 6 | ## 1. 字符串基础 7 | 8 | python 中 三种字符串独立等价 9 | 10 | (''), (""),(""" """) 11 | 12 | 字符串内有转义字符 13 | 14 | 15 | ![](http://ww3.sinaimg.cn/large/006tNc79ly1g41x9m2iedj30us0duwfr.jpg) 16 | 17 | ```python 18 | 19 | >>> s = 'a\nb\tc' 20 | >>> print(s) 21 | a 22 | b c 23 | >>> len(s) 24 | 5 25 | 26 | ``` 27 | 28 | 转义字符也算一个字符 29 | 30 | ## 2. 字符串常用操作 31 | 32 | 1. 字符串相当于丹个字符组成的数组, 支持 **索引,切片和遍历** 33 | 34 | 35 | 2. 字符串是不可变的(immutable) 36 | 37 | ```python 38 | >>> s = 'hello' 39 | >>> s[0] = 'H' 40 | Traceback (most recent call last): 41 | File "", line 1, in 42 | TypeError: 'str' object does not support item assignment 43 | 44 | ``` 45 | 46 | ```python 47 | 48 | s = 'H' + s[1:]. # 新建字符, 拼接 49 | 50 | s = s.replace('h','H') # 扫描原来的字符串, 替换字符, 51 | 52 | ``` 53 | 54 | 上面的方法改变字符串, 需要 O(n) 的时间复杂度。 55 | 56 | 57 | **Python 中性能优化方法** --- ‘+=’ 58 | 59 | ```python 60 | 61 | str2 += str1 62 | ``` 63 | 64 | 上面的字符串拼接操作,Python 会首先检测 str1 是否存在其他的引用,如果没有,Python 会尝试扩充字符串 buffer 的大小,而不是重新分配内存创建新的字符串并拷贝, 时间复杂度从 O(n) -- > O(1). 65 | 66 | 67 | 3. 字符串拼接 68 | 69 | ```python 70 | s = '' 71 | for n in range(0, 100000): 72 | s += str(n) 73 | 74 | ``` 75 | 76 | 等价于 77 | 78 | ```python 79 | 80 | l = [] 81 | for n in range(0, 100000): 82 | l.append(str(n)) 83 | l = ' '.join(l) 84 | 85 | ``` 86 | join 函数,是 字符串内置的 函数,用来吧每个元素按照指定的格式连接起来。 87 | 88 | 89 | 等价于 90 | 91 | ```python 92 | 93 | s = " ".join(map(str,range(1000))) 94 | ``` 95 | 96 | map 函数 97 | 98 | map函数的原型是map(function, iterable, …),它的返回结果是一个列表。 99 | 100 | function 是函数名,可以是自定义的,也可以是内置的函数。 101 | iterable传的是一个可以迭代的对象,例如列表,元组,字符串 102 | 103 | function应用于iterable的每一个元素,结果以列表的形式返回 104 | 105 | 106 | 4. 字符串的分割 107 | 108 | ```python 109 | 110 | string.split(sepratator) 111 | 112 | ``` 113 | 114 | 字符串分割成多个子字符串,返回一个子字符串组合的列表。 115 | 116 | ```python 117 | 118 | >>> path = 'hive://ads/training_table' 119 | >>> namespace = path.split('//')[1].split('/')[0] 120 | >>> namespace 121 | 'ads' 122 | 123 | ``` 124 | 125 | 5. 去除字符串 126 | 127 | * 去除首尾的: string.strip() 128 | * 去除首部的: string.lstrip() 129 | * 去除尾部的: string.rstrip() 130 | 131 | 例如开头和结尾存在 空字符 132 | 133 | ```python 134 | s= ' Hello. world ' 135 | s.strip() 136 | ``` 137 | 138 | 139 | ## 字符串格式化 140 | 141 | Python 最新规范 : format 函数 142 | 143 | ```python 144 | 145 | print("no data available for person with id: {} , ; name: {}".format(id, name)) 146 | ``` 147 | 148 | 149 | 150 | 151 | 152 | # 参考 153 | 154 | 1. https://blog.csdn.net/csdn15698845876/article/details/73321593 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /Python/python 中常用迭代方法.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | 4 | ### 1. 同时迭代两个列表 5 | 6 | ```python 7 | list_1 = [1,3,4] 8 | list_2 = ['first','second','third'] 9 | for i ,i_en in zip(list_1,list_2): 10 | print(str(i)+i_en) 11 | 12 | ``` 13 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/rmf57.jpg) 14 | 15 | 16 | 17 | 18 | ---- 19 | 20 | ### 2. 带索引的列表迭代 21 | 22 | ```python 23 | list_2 = ['first','second','third'] 24 | for index ,i_en in enumerate(list_2): 25 | print(index,i_en) 26 | ``` 27 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/4ij4i.jpg) 28 | 29 | ---- 30 | 31 | ### 3. 列表推导(list comprehensions) 32 | 33 | ```python 34 | numbers = [1,2,3,4,5,6] 35 | even = [number for number in numbers if number%2 == 0] 36 | ``` 37 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/3v6vv.jpg) 38 | 39 | ---- 40 | ### 4. 字典推导(Dictionary comprehension 41 | 42 | ```python 43 | list_2 = ['first','second','third'] 44 | dic = {key: value for value ,key in enumerate(list_2)} 45 | print(dic) 46 | ``` 47 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ng6g0.jpg) 48 | 49 | ---- 50 | 51 | ### 5. 迭代工具 --- itertools 52 | 53 | 查找所有的组合方式 54 | 55 | 56 | ```python 57 | from itertools import combinations 58 | list_2 = ['first','second','third'] 59 | for comb in combinations(list_2,2): 60 | print(comb) 61 | ``` 62 | 63 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/emxey.jpg) 64 | 65 | ---- 66 | 67 | # 参考 68 | 69 | 1. https://mp.weixin.qq.com/s/ThktUK0m8tIxk2mTwkR-Tw 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Python/python 中条件和循环.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 条件语句 6 | 7 | ```python 8 | 9 | if condition_1: 10 | statement_1 11 | elif condition_2: 12 | statement_2 13 | ... 14 | elif condition_i: 15 | statement_i 16 | else: 17 | statement_n 18 | 19 | 20 | ``` 21 | 22 | 基本的 条件语句, 顺序执行, 遇到一个条件满足,执行完 statement 之后,退出整个条件语句。 23 | 24 | ![](http://ww3.sinaimg.cn/large/006tNc79ly1g438mw670bj31b60i5tce.jpg) 25 | 26 | ----- 27 | 28 | 29 | ## 2. 循环语句 30 | 31 | 1. for 循环 32 | 33 | 数据结构是可以迭代的,都可以遍历 (iterable) 34 | 35 | 字典 : 本身只有 key 可以迭代, 36 | 37 | ```python 38 | 39 | >>> for k in liu: 40 | ... print(k) 41 | 42 | name 43 | age 44 | height 45 | gender 46 | 47 | ``` 48 | 49 | 如果遍历 value 或者 key-value 对,需要调用内置函数。 50 | 51 | ```python 52 | 53 | >>> for v in liu.values(): 54 | ... print(v) 55 | ... 56 | liu 57 | 23 58 | 80 59 | male 60 | 61 | ``` 62 | 63 | ```python 64 | 65 | >>> for k, v in liu.items(): 66 | ... print("key:{},value:{}".format(k,v)) 67 | ... 68 | key:name,value:liu 69 | key:age,value:23 70 | key:height,value:80 71 | key:gender,value:male 72 | 73 | ``` 74 | 75 | 2. while 循环 76 | 77 | ```python 78 | 79 | l = [1, 2, 3, 4] 80 | index = 0 81 | while index < len(l): 82 | print(l[index]) 83 | index += 1 84 | 85 | ``` 86 | 87 | 3. continue 和 break 语句 88 | 89 | continue : 跳出当前这层循环, 继续执行下面的循环。 90 | break : 完全跳出循环体 91 | 92 | 93 | 4. while 和 for 的 比较 94 | 95 | for : 遍历一个已知的集合 96 | while: 没有特定的集合需要去遍历 97 | 98 | 99 | while和 for 的效率问题: 100 | 101 | ```python 102 | i = 0 103 | while i < 1000000: 104 | i += 1 105 | ``` 106 | 107 | ```python 108 | 109 | for i in range(0, 1000000): 110 | pass 111 | ``` 112 | 113 | range 是基于 c 语言的, 调用的速度很快 114 | 115 | while 中的 i+= 1,设计到了对象的创建和删除, 116 | > i 是 immutable, i = new int(i + 1) 117 | 118 | ------ 119 | 120 | 121 | ## 3. 条件和循环的复合使用 122 | 123 | 124 | 125 | ```python 126 | 127 | expression1 if condition else expression2 for item in iterable 128 | 129 | ``` 130 | 131 | 等价于 132 | 133 | ```python 134 | for item in iterable: 135 | if condition: 136 | expression1 137 | else: 138 | expression2 139 | 140 | ``` 141 | 142 | 如果没有 else 语句 143 | 144 | ```python 145 | 146 | expression for item in iterable if condition 147 | 148 | ``` 149 | 150 | 151 | 同时两个循环 : 152 | 153 | 返回两个列表元素组成的元组 154 | 155 | ```python 156 | 157 | [(xx,yy) for xx in x for yy in y if x != y] 158 | 159 | ``` 160 | 161 | 等价于 162 | 163 | ```python 164 | l = [] 165 | for xx in x : 166 | for yy in y : 167 | if xx != yy 168 | l.append((xx,yy)) 169 | 170 | ``` 171 | 172 | ---- 173 | 174 | ## 4. 例题 : 175 | 176 | ```python 177 | 178 | attributes = ['name', 'dob', 'gender'] 179 | values = [['jason', '2000-01-01', 'male'], 180 | ['mike', '1999-01-01', 'male'], 181 | ['nancy', '2001-02-01', 'female'], 182 | ['liu','1997-04-15','male'] 183 | ] 184 | 185 | # expected outout: 186 | [{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}, 187 | {'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'}, 188 | {'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}] 189 | 190 | ``` 191 | 192 | 193 | 194 | ```python 195 | 196 | outout =[] 197 | 198 | for i in range(len(values)): 199 | dict1 = {} 200 | for j in range(len(values[0])): 201 | dict1[attributes[j]] = values[i][j] 202 | outout.append(dict1) 203 | ``` 204 | 205 | 206 | ```python 207 | [ dict(zip(attributes,value))for value in values] 208 | 209 | ``` 210 | 211 | zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同。利用 * 号操作符,可以将list unzip(解压) 212 | 213 | ```python 214 | 215 | >>> a = [1,2,3] 216 | >>> b = [4,5,6] 217 | >>> c = [4,5,6,7,8] 218 | >>> zipped = zip(a,b) 219 | [(1, 4), (2, 5), (3, 6)] 220 | >>> zip(a,c) 221 | [(1, 4), (2, 5), (3, 6)] 222 | >>> zip(*zipped) 223 | [(1, 2, 3), (4, 5, 6)] 224 | 225 | ``` 226 | 227 | # 参考 228 | 229 | 1. zip 函数 ---- https://www.jb51.net/article/53051.htm 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /Python/python 中自定义函数.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | 6 | ## 1. 函数的基础 7 | 8 | 1. 函数基本形式: 9 | 10 | ```python 11 | 12 | def name(param1, param2, ..., paramN): 13 | statements 14 | return/yield value # optional 15 | 16 | ``` 17 | 18 | 2. 和其他的需要编译的语言不一样, python 中的 **def 是可执行语句**,函数知道被调用前都是不存在的的。当程序调用函数的时候, def 语句才会创建一个新的函数对象,赋予名字 19 | 20 | 21 | 3. Python 是 dynamically typed 的, 可以接受任何数据类型(整型,浮点型,字符串等),函数的参数传递可以人很数据类型。 22 | 23 | ```python 24 | def sum_test(a,b): 25 | return a+b 26 | sum_test(1,2) 27 | 28 | >>> sum_test(1,2) 29 | 3 30 | 31 | >>> sum_test([1,2],[3,4]) 32 | [1, 2, 3, 4] 33 | >>> sum_test("liu","chuang") 34 | 'liuchuang' 35 | 36 | ``` 37 | 38 | 不考虑输入的数据类型,交给具体的代码去判断,这种行为称为 **多态** 39 | 40 | 41 | 42 | ## 2. 函数的嵌套 43 | 44 | ```python 45 | 46 | def f1(): 47 | print("hello") 48 | def f2(): 49 | print("world") 50 | f2() 51 | 52 | >>> f1() 53 | hello 54 | world 55 | 56 | ``` 57 | 函数嵌套的作用: 58 | 59 | * 保证内部数据的隐私 60 | 61 | ```python 62 | 63 | def connect_DB(): 64 | def get_DB_configuration(): 65 | ... 66 | return host, username, password 67 | conn = connector.connect(get_DB_configuration()) 68 | return conn 69 | ``` 70 | 71 | 上面获取用户的 姓名密码等 函数封装在连接函数内,是内部函数,无法外部调用。 72 | 73 | 74 | * 提高程序的运行效率 75 | 76 | 77 | ```python 78 | 79 | def factorial(n): 80 | """ 81 | 计算一个数字的阶乘 82 | 先检查输入的合法性 83 | 84 | """ 85 | if not isinstance(n , int): 86 | raise Exception('Input must be integer') 87 | if n < 0: 88 | raise Exception(" Input must > 0") 89 | 90 | def calculate_fac(n): 91 | if n <= 1: 92 | return 1 93 | else: 94 | return n * calculate_fac(n-1) 95 | return calculate_fac(n) 96 | 97 | ``` 98 | 99 | 计算之前需要检查输入是否合法, 只是定义一个函数, 每次递归调用都需要检查一次,降低程序的运行效率,耗费资源。 100 | 写成嵌套函数, 只需要检查一次。 101 | 102 | 103 | 104 | --- 105 | 106 | ## 3. 函数的变量作用域 107 | 108 | 变量是在函数内部定义的,称为局部变量,只在函数的内部有效,函数执行完毕,局部变量回收,无法访问。 109 | 110 | 全局变量: 定义在整个文件层次 111 | 112 | 1. **不能在函数内部随意改变全局变量的值** 113 | 114 | 115 | ```python 116 | 117 | Min = 1 118 | 119 | def value_square(value): 120 | Min = Min * Min 121 | 122 | >>> value_square(2) 123 | Traceback (most recent call last): 124 | File "", line 1, in 125 | File "", line 2, in value_square 126 | UnboundLocalError: local variable 'Min' referenced before assignment 127 | 128 | ``` 129 | 130 | Python 解释器会默认函数内部的变量为局部变量, 局部变量 Min 并没有声明。 131 | 132 | 2. 一定要改变全局变量的值, 必须加上 global。 133 | global 告诉 Python 解释器,函数内部变量 Min , 就是之前定义的全局变量。 134 | 135 | 136 | 137 | ```python 138 | 139 | Min = 2 140 | 141 | def value_square(value): 142 | global Min 143 | Min = Min * Min 144 | ``` 145 | 146 | 3. 全局变量和 局部变量命名冲突 147 | 148 | 在函数内部, 局部变量会覆盖全局变量 149 | 150 | 151 | 152 | 4. 嵌套函数 153 | 154 | 内部函数可以访问外部函数定义的变量,但是不能修改。 想要修改,需要加入 nonlocal 关键字 155 | 156 | ```python 157 | 158 | def outer(): 159 | x = 1 160 | def inner(): 161 | nonlocal x 162 | x = 3 163 | print("inner :", x) 164 | inner() 165 | print("outer", x) 166 | outer() 167 | 168 | >>> outer() 169 | inner : 3 170 | outer 3 171 | 172 | ``` 173 | 加入 关键字之后,成功修改外层函数定义的数值 174 | 175 | 176 | 177 | --- 178 | 179 | ## 4. 闭包 closure 180 | 181 | 类似于嵌套函数, 只不过外部函数返回的是一个函数,而不是具体的值 182 | 183 | 例如 : 外部函数 返回函数 exponent_of() 184 | 185 | ```python 186 | def nth_power(exponent): 187 | def exponent_of(base): 188 | return base ** exponent 189 | return exponent_of 190 | 191 | square = nth_power(2) 192 | cube = nth_power(3) 193 | 194 | >>> square = nth_power(2) 195 | >>> cube = nth_power(3) 196 | >>> square 197 | .exponent_of at 0x105fc20d0> 198 | >>> square(2) 199 | 4 200 | 201 | ``` 202 | 203 | 闭包的优势: 204 | 205 | * 程序简单易读 206 | 207 | 208 | * 函数开头需要一些额外的工作, 多次调用函数的时候,就可以将函数放在外部函数,减少多次调用导致的不必要的开销 209 | 210 | 211 | 存在一些 参数性 而且不常改变的量的时候,使用闭包函数, 只需要关注核心的输入变量,减少全局变量的使用 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /Python/python 中输入和输出.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 输入输出基础 6 | 7 | 1. input() 函数 8 | 9 | 10 | input 函数暂停程序的运行,等待键盘的输入, 11 | 12 | 输入的类型永远是字符串型(str) 13 | 14 | 需要输入数字需要 int ,float 等强制转换 15 | 16 | ----- 17 | 18 | 19 | 20 | ## 2. 文件的输入输出 21 | 22 | 计算机文件访问的基础知识: 23 | 24 | 1. open() 函数拿到文件的指针, 第一个参数是文件的绝对位置或者相对位置;第二个参数 表示文件读取。 25 | 26 | ```python 27 | with open('test.txt','r') as fin 28 | 29 | ``` 30 | 31 | PS: 使用 open() 函数,完成读取任务之后需要立即关掉它, 使用了 with 语句,就不需要显示的调用 close(). 32 | 33 | 2. 拿到文件的指针之后, 通过 read() 函数,读取文件的全部内容 34 | 35 | ```python 36 | 37 | text = fin.read() 38 | ``` 39 | * 这样读取如果文件过大, 一次性读取可能造成内存崩溃 40 | 41 | read() 函数加入 size 参数 42 | readline() 函数每次读取一行 43 | 44 | ---- 45 | 46 | 47 | ## 3. JSON 序列化 48 | 49 | 50 | JSON : 轻量级数据交换格式,所有的事情(字符串,整数型,浮点数型,布尔型变量)都使用 字符串表示。 51 | 52 | * 输入 所有类型数据, 输出一个字符串 53 | * 输入一个字符串, 输出所有的信息 54 | 55 | 56 | ```python 57 | 58 | >>> import json 59 | >>> liu = {"name":"liu","age" : 23, "height": 80, "gender":"male"} 60 | >>> liu_str = json.dumps(liu) 61 | >>> print("type of liu_str is {}, liu_str is {}.".format(type(liu_str),liu_str)) 62 | 63 | type of liu_str is , liu_str is {"name": "liu", "age": 23, "height": 80, "gender": "male"}. 64 | 65 | >>> original_liu = json.loads(liu_str) 66 | 67 | >>> print("type of original_liu is {}, liu is {}.".format(type(original_liu),original_liu)) 68 | type of original_liu is , liu is {'name': 'liu', 'age': 23, 'height': 80, 'gender': 'male'}. 69 | ``` 70 | 71 | json.dumps() : 接收python 的基本数据类型, 序列化为 string 72 | 73 | json.loads() : 接收字符串, 反序列化为 python的 基本数据类型 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /Python/python 列表和元组.md: -------------------------------------------------------------------------------- 1 | 2 | tuple1 = (1, "liu") 3 | ``` 4 | 5 | 6 | * 列表是 动态的(mutable), 长度大小不固定, 7 | * 元组的大小是固定的 , 8 | 9 | 如果想对元组进行改变,只能开辟一块新的内存,创建新的元组。 10 | 11 | ```python 12 | >>> tup = (1,2,3) 13 | >>> new_tup = tup + (5) 14 | Traceback (most recent call last): 15 | File "", line 1, in 16 | TypeError: can only concatenate tuple (not "int") to tuple 17 | >>> new_tup = tup + (5,) 18 | >>> new_tup 19 | (1, 2, 3, 5) 20 | ``` 21 | 22 | 23 | ## 2. 基本操作 24 | 25 | 1. 支持负数索引 26 | ```python 27 | list1 = [1,2 "liu"] 28 | list1[-1]. 29 | 30 | tuple1 = (1, "liu") 31 | tuple1[-1] 32 | ``` 33 | - 1 表示最后一个元素。 34 | 35 | 36 | 2. 支持切片操作 37 | 38 | ```python 39 | list1 = [1,2 "liu"] 40 | list1[1:3]. 41 | 42 | tuple1 = (1, "liu") 43 | tuple1[1:3] 44 | ``` 45 | 46 | 47 | 3. 支持嵌套 48 | 49 | 50 | ```python 51 | list1 = [1,2 "liu",[1,2,3]] 52 | list1[1:3]. 53 | 54 | tuple1 = (1, "liu",(1,"liu")) 55 | tuple1[1:3] 56 | ``` 57 | 58 | 59 | 4. 相互转换 60 | 61 | ```python 62 | list1 = [1,2 "liu"] 63 | tuple(list1) 64 | 65 | tuple1 = (1, "liu") 66 | list(tuple1) 67 | ``` 68 | 69 | 5. 常用内置函数 70 | 71 | * count : item 出现的次数 72 | * index: 第一次出现的索引 73 | * list.reverse, list.sort() : 倒转和排序 74 | * reversed(),sorted(): 返回 列表或者元组 75 | 76 | 77 | ## 3. 列表元组储存方式的差异 78 | 79 | ```python 80 | >>> l = [1,2,3] 81 | >>> l.__sizeof__() 82 | 64 83 | >>> tup = (1,2,3) 84 | >>> tup.__sizeof__() 85 | 48 86 | >>> 87 | ``` 88 | 89 | 90 | 相同的元素,元组的储存空间比列表要少 16 字节 91 | 92 | * 列表是动态的, 需要储存指针, 8 字节 93 | 94 | * 列表可变, 额外储存已经分配长度的大小 , 8 字节 95 | 96 | ```python 97 | >>> l = [] 98 | >>> l.__sizeof__() 99 | 40 # 空列表储存空间 40 100 | >>> l.append(1) 101 | >>> l.__sizeof__() 102 | 72 # 列表分配了 4个 元素的空间, 每个元素的空间 8 103 | >>> l.append(2) 104 | >>> l.__sizeof__() 105 | 72 106 | >>> l.append(2) 107 | >>> l.__sizeof__() 108 | 72 109 | >>> l.append(2) 110 | >>> l.__sizeof__() 111 | 72 112 | >>> l.append(2) 113 | >>> l.__sizeof__() 114 | 104 # 空间不足, 额外分配 4 个 元素的空间 115 | 116 | ``` 117 | 118 | 119 | 为了减小 删除和添加的时候空间分配的开销, 每次分配空间都会多分配一些, 这个机制保证了操作的高效性, 删除添加的时间复杂度都是 O(1) 120 | 121 | 122 | ## 4. 列表和元组的性能 123 | 124 | * 元组比列表要轻量, 性能速度要略优于列表 125 | 126 | 127 | * python 中垃圾回收机制, 如果一些变量不被使用, python回收占用的内存, 但是杜预一些静态变量 -- 元组, 不被使用, python 回暂时缓存这部分内存, 在创建同样大小的元组的时候, 不必寻找内存, 直接分配之前缓存的内存, 加快运行速度。 128 | 129 | 130 | ```python 131 | >>> timeit.timeit('a= []',number= 10000) 132 | 0.00041297206189483404 133 | >>> timeit.timeit('a= ()',number= 10000) 134 | 0.00041262293234467506 135 | 136 | 137 | timeit.timeit('a= (1,2, 3,4 ,5)',number= 10000) 138 | 0.0001837840536609292 139 | >>> timeit.timeit('a= [1,2, 3,4 ,5]',number= 10000) 140 | 0.000875954981893301 141 | 142 | 143 | >>> timeit.timeit('a= (1,2, 3,4 ,5,6,7,7,8,8,9,9,5,5,5,5,5,5,5,5)',number= 10000) 144 | 0.0002209079684689641 145 | >>> timeit.timeit('a= [1,2, 3,4 ,5,6,7,7,8,8,9,9,5,5,5,5,5,5,5,5]',number= 10000) 146 | 0.0016364289913326502 147 | 148 | ``` 149 | 150 | tuple 初始化,速度优于 list, 数组越大,优势越明显。 151 | 152 | 153 | 154 | ## 5. 列表和元组的使用场景 155 | 156 | 1. 储存的数据和数量不变 --- 元组 157 | 158 | 2. 输出或者数量可变 --- 列表 159 | 160 | 161 | 162 | ## 6. 创建列表方式 163 | 164 | ```python 165 | list2 - [] 166 | 167 | list3 = list() 168 | 169 | ``` 170 | 171 | list() 是一个 python调用函数, 需要进行一系列参数检查的操作 172 | 173 | [] 是内置的 C 函数, 直接调用 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /Python/python 参数传递.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《 python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | 6 | ## 1. Python 变量及其赋值 7 | 8 | 1. 不可变的变量 9 | 10 | ```python 11 | 12 | a = 1 13 | b = a 14 | a = a + 1 15 | 16 | ``` 17 | 18 | * a= 1 , 变量 a 指向 1 这个对象 19 | 20 | * b= a , 变量 b 同时也指向 1 这个对象 (对象可以被多个变量指向和引用) 21 | 22 | * a = a+1 , python 中数据类型 int string 是不可变的, 所以, 重新创建一个 对象 让 a 指向他, b 仍指向 1 23 | 24 | 25 | 2. 可变的变量 26 | 27 | 28 | ```python 29 | 30 | l1 = [1, 2, 3] 31 | l2 = l1 32 | l1.append(4) 33 | l1 34 | [1, 2, 3, 4] 35 | l2 36 | [1, 2, 3, 4] 37 | 38 | ``` 39 | 40 | l1 和 l2 同时指向了 [1,2,3] 这个对象 41 | 42 | 列表是可变的, 不会创建新的列表, 所以 l1 和 l2 的值 同时改变。 43 | 44 | 45 | 3. 变量可以删除, 对象无法删除 46 | 47 | ```python 48 | l = [1, 2, 3] 49 | del l 50 | 51 | ``` 52 | 53 | 删除了 l ,但是对象 [1,2,3] 还在。 python 程序云心烦的时候, 自带的垃圾回收系统会跟踪每个对象的引用, 54 | 55 | 如果对象 [1,2,3] 还在其他的地方被引用,就不会回收, 否则会被回收。 56 | 57 | 58 | --- 59 | 60 | 61 | ## 2. python 函数的参数传递 62 | 63 | Python 的参数传递都是赋值传递(pass by assignment), 对象的引用传递,python 中参数传递的时候 只是让新变量和原始变量指向相同的对象。 64 | 65 | 66 | ### 1. 不可变对象 67 | 68 | ```python 69 | 70 | def my_func1(b): 71 | b = 2 72 | 73 | a = 1 74 | my_func1(a) 75 | a 76 | 1 77 | 78 | ``` 79 | 80 | 81 | 1. my_func() 进行参数传递, 使得变量 a 和变量 b 同时指向了一个对象。 82 | 2. 当执行下面的 b= 2 的时候, 由于 不可变 系统会创建一个值为 2 的新的对象,b 指向 2 83 | 3. a 仍然指向 1 这个对象 84 | 85 | 86 | 87 | ```python 88 | def my_func2(b): 89 | b = 2 90 | return b 91 | 92 | a = 1 93 | a = my_func2(a) 94 | a 95 | 2 96 | 97 | ``` 98 | 99 | 1. 返回的新变量赋值给了 a, 因此 a 的值也变成了 2 100 | 101 | 102 | ### 2. 可变对象 103 | 104 | 105 | ```python 106 | def my_func3(l2): 107 | l2.append(4) 108 | 109 | l1 = [1, 2, 3] 110 | my_func3(l1) 111 | l1 112 | [1, 2, 3, 4] 113 | 114 | ``` 115 | 116 | 1. l1 和 l2 同时指向 [1,2,3] 列表。 117 | 2. 由于列表可变, 执行 append() 函数,变量 l1 和 l2 值 也改变 118 | 119 | 120 | ```python 121 | def my_func4(l2): 122 | l2 = l2 + [4] 123 | 124 | l1 = [1, 2, 3] 125 | my_func4(l1) 126 | l1 127 | [1, 2, 3] 128 | 129 | ``` 130 | 1. 这里的 l2 + 表示创建了 一个新的列表, 并让 l2 指向 新的对象。 131 | 132 | 2. 过程与 l1 无关, l1 的值不会改变 133 | 134 | 135 | * 如果要改变 l1 的值, 就得让上述的函数返回值, 赋予给 l1 136 | 137 | 138 | 139 | ```python 140 | 141 | def my_func5(l2): 142 | l2 = l2 + [4] 143 | return l2 144 | 145 | l1 = [1, 2, 3] 146 | l1 = my_func5(l1) 147 | l1 148 | [1, 2, 3, 4] 149 | 150 | ``` 151 | 152 | 153 | ---- 154 | 155 | 156 | ## 3. 思考题 157 | 158 | 159 | ```python 160 | 161 | l1 = [1, 2, 3] 162 | l2 = [1, 2, 3] 163 | l3 = l2 164 | 165 | ``` 166 | 167 | 1,2,3 是否指向同一个对象? 168 | 169 | 2,3 指向同一个对象, 1,2 指向不同的内存空间 170 | 171 | 172 | ```python 173 | 174 | def func(d): 175 | d['a'] = 10 176 | d['b'] = 20 177 | 178 | d = {'a': 1, 'b': 2} 179 | func(d) 180 | print(d) 181 | 182 | 183 | ``` 184 | 最后的输出 185 | 186 | 187 | 188 | ```python 189 | {'a': 10, 'b': 20} 190 | 191 | ``` 192 | 193 | 因为 字典是可变, 传入函数之后, 函数的内部和外部 d 都是指向同一个对象 194 | 195 | 196 | --- 197 | 198 | ## 4. 补充 199 | 200 | python 里面的一切都是对象: 201 | 202 | 203 | 例如 a = 1 : 先是在内存中申请一份空间, 存下值= 1 , 然后再给这块空间贴上标签,叫做变量 a . 204 | 205 | 通过储存的值可以推断变量的类型, 由解释器完成。 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /Python/python 迭代器和生成器.md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《 python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | ## 1. 可迭代对象 和 迭代器 6 | 7 | 1. 容器 : python 中一切都是对象,对象的抽象是类, 对象的集合就是容器 8 | 9 | 例如,列表,元组, 字典, 集合等都是容器。 10 | 11 | 12 | 2. 所有的容器都是可以迭代的(iterable). 13 | 14 | 3. 迭代器提供了一个 next 的方法, 调用这个方法之后, 要么得到下一个对象,要么得到一个 stopiteration; next 15 | 方法可以不遗漏的一个个拿到所有的元素。 16 | 17 | 4. 对于可以迭代对象, iter() 函数返回一个迭代器, 通过 next() 函数实现遍历 18 | 19 | 5. 判断一个对象是否是可迭代的 20 | 21 | ```python 22 | 23 | def is_iterable(param): 24 | try: 25 | iter(param) 26 | return true 27 | except TypeError: 28 | return False 29 | ``` 30 | 31 | 32 | ---- 33 | 34 | ## 2. 生成器 35 | 生成器是简化的 迭代器 36 | 37 | 1. 声明一个迭代器 [ i for i in range(10000)] 生成元素列表, 每个元素生成后都会保存在内存中,占用大量的内存 38 | 39 | 2. 有时候不需要保存全部的元素, 用完就可以扔掉了 40 | 41 | 3. 生成器 : 只有调用 next() 函数的时候,才会生成下一个变量。 (i for i in range(10000)) 42 | 43 | 44 | 45 | ```python 46 | 47 | def generator(k): 48 | i = 1 49 | while True : 50 | yield i**k 51 | i = i+1 52 | 53 | print(generator(1)) 54 | 55 | 56 | gen_1 = generator(1) 57 | gen_3 = generator(3) 58 | def get_sum(n): 59 | sum_1 , sum_3 = 0,0 60 | for i in range(n): 61 | next_1 = next(gen_1) 62 | next_3 = next(gen_3) 63 | print("next 1 = {} ,next 3 = {}".format(next_1,next_3)) 64 | sum_1 += next_1 65 | sum_3 += next_3 66 | print(sum_1*sum_1, sum_3) 67 | 68 | 69 | ################# 70 | next 1 = 1 ,next 3 = 1 71 | next 1 = 2 ,next 3 = 8 72 | next 1 = 3 ,next 3 = 27 73 | 36 36 74 | 75 | ``` 76 | 77 | yeild 函数 会使程序跳出, 跳到 next() 函数 78 | 79 | 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。 在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。 80 | 81 | ---- 82 | 83 | ## 3. 生成器 应用 84 | 85 | 1. 查询指定数字在 list 中的位置 86 | 87 | ```python 88 | def index_generator(L, target): 89 | for i , num in enumerate(L): 90 | if num == target: 91 | yield i 92 | 93 | 94 | 95 | print(list(index_generator([1,2,3,4,1,2,3,4,1,2,3,4], 1))) 96 | [0, 4, 8] 97 | 98 | ``` 99 | 100 | 2. 给定两个序列, 判断是否是子序列 101 | 102 | ```python 103 | 104 | def is_subsequence(a,b): 105 | b = iter(b) # 将列表转换成 迭代器 106 | print(b) 107 | 108 | gen = (i for i in a) # 列表转换成一个生成器 109 | 110 | for i in gen: 111 | print(i) 112 | 113 | gen = ((i in b ) for i in a ) 114 | print(gen) 115 | 116 | 117 | for i in gen: 118 | print(i) 119 | 120 | return all(((i in b ) for i in a )) 121 | 122 | print(is_subsequence([1,2,3],[1,2,3,4,5])) 123 | 124 | 1 125 | 2 126 | 3 127 | . at 0x10b551b48> 128 | True 129 | True 130 | True 131 | False 132 | 133 | ``` 134 | 135 | gen = ((i in b ) for i in a ) 136 | 137 | 等价于 138 | 139 | ```python 140 | 141 | while True : 142 | val = next(b) 143 | if val == i : 144 | yield True 145 | ``` 146 | 这样保存了 当前的指针, 可以继续判断 147 | 148 | 149 | all 判断是否全部为 true , 如果是,返回 true, 否则返回 false 150 | 151 | 最后 返回 false 是因为 152 | 153 | for i in gen 已经把 迭代器 消耗完了, b 已经是一个空的迭代器, 再执行 all() 就是 false 154 | (需要复位生成器才能重新进行遍历) 155 | 156 | 157 | 158 | ---- 159 | 160 | 简化代码: 161 | 162 | ```python 163 | 164 | def is_subsequence(a,b): 165 | b = iter(b) 166 | return all(i in b for i in a) 167 | 168 | 169 | print(is_subsequence([1, 3, 5], [1, 2, 3, 4, 5])) 170 | True 171 | 172 | print(is_subsequence([1,5, 3], [1, 2, 3, 4, 5])) 173 | False 174 | 175 | ``` 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /Python/python小技巧 : 函数参数解包(*, **).md: -------------------------------------------------------------------------------- 1 | Python 3.6.5 2 | 3 | 4 | ---- 5 | 6 | 7 | ## 1. tuple and list 8 | 9 | ```python 10 | def print_vector(x,y,z): 11 | print(" ( {},{},{} )".format(x,y,z)) 12 | 13 | ``` 14 | 15 | 1. 直接打印 tuple 会报错,因为值传递了一个值 tuple 16 | 17 | ```python 18 | >>> tuple_vec = (1,2,3) 19 | >>> print_vector(tuple_vec) 20 | Traceback (most recent call last): 21 | File "", line 1, in 22 | TypeError: print_vector() missing 2 required positional arguments: 'y' and 'z' 23 | 24 | ``` 25 | 26 | 2. 手动逐个给定 27 | 28 | ```python 29 | print_vector(tuple_vec[0],tuple_vec[1],tuple_vec[2]) 30 | ( 1,2,3 ) 31 | 32 | 33 | ``` 34 | 35 | 36 | 3. 使用 * , 达到同样的效果 37 | 38 | ```python 39 | 40 | print_vector(*tuple_vec) 41 | ( 1,2,3 ) 42 | 43 | ``` 44 | 45 | 46 | 47 | 4. 同理 list 48 | 49 | ```python 50 | >>> list_vec = [1,2,3] 51 | >>> print_vector(*list_vec) 52 | ( 1,2,3 ) 53 | 54 | ``` 55 | 56 | 57 | 58 | ## 2. 字典 59 | 60 | 61 | 62 | 3.6+ 版本,字典是有顺序的 63 | 64 | ```python 65 | >>> dict_vec = {'x': 1, 'y': 2, 'z': 3} 66 | >>> print_vector(*dict_vec) 67 | ( x,y,z ) 68 | >>> print_vector(**dict_vec) 69 | ( 1,2,3 ) 70 | ``` 71 | 72 | 73 | 74 | 75 | **向一个函数中 传递不同的数据类型** 76 | 77 | ---- 78 | 79 | # 参考 80 | 81 | real python --https://realpython.com/ -------------------------------------------------------------------------------- /Python/python小技巧 : 字典按照 value 排序.md: -------------------------------------------------------------------------------- 1 | Python 3.6.5 2 | 3 | 4 | ---- 5 | 6 | 7 | 1. 默认 按照 key 值排序 8 | ```python 9 | >>> xs = {'a': 4, 'c': 3, 'b': 2, 'd': 1} 10 | >>> sorted(xs.items()) 11 | [('a', 4), ('b', 2), ('c', 3), ('d', 1)] 12 | ``` 13 | 14 | 15 | 2. 指定 按照 value 排序 16 | ```python 17 | 18 | >>> xs = {'a': 4, 'b': 3, 'c': 2, 'd': 1} 19 | >>> sorted(xs.items(), key = lambda x: x[1]) 20 | [('d', 1), ('c', 2), ('b', 3), ('a', 4)] 21 | 22 | ``` 23 | 24 | 25 | ```python 26 | >>> xs = {'a': 4, 'b': 3, 'c': 2, 'd': 1} 27 | >>> import operator 28 | >>> sorted(xs.items(), key=operator.itemgetter(1)) 29 | [('d', 1), ('c', 2), ('b', 3), ('a', 4)] 30 | 31 | ``` 32 | 33 | 34 | 35 | ---- 36 | 37 | # 参考 38 | 39 | real python --https://realpython.com/ -------------------------------------------------------------------------------- /Python/python小技巧 :namedtuples 简洁定义class.md: -------------------------------------------------------------------------------- 1 | Python 3.6.5 2 | 3 | ---- 4 | 5 | 使用 nametuples 来定义一个 class 6 | 7 | ```python 8 | >>> from collections import namedtuple 9 | >>> Student = namedtuple('Student','age score') 10 | >>> liu = Student(18,90) 11 | >>> liu.age 12 | 18 13 | >>> liu.score 14 | 90 15 | >>> liu 16 | Student(age=18, score=90) 17 | 18 | 19 | ``` 20 | 21 | 22 | 23 | namedtuple 创建的 类和 tuples 相同, 不可进行更改 24 | 25 | ```python 26 | 27 | >>> liu.score = 89 28 | Traceback (most recent call last): 29 | File "", line 1, in 30 | AttributeError: can't set attribute 31 | 32 | ``` -------------------------------------------------------------------------------- /Python/python小技巧 :字典中的 get() 方法.md: -------------------------------------------------------------------------------- 1 | Python 3.6.5 2 | 3 | ---- 4 | 5 | ```Python 6 | 7 | 8 | name_id = { 9 | 1:"liu", 10 | 2:"zou", 11 | 3:"li", 12 | } 13 | 14 | 15 | def hello(id): 16 | return "Hello, {}".format(name_id.get(id,"Everybody")) 17 | 18 | >>> hello(1) 19 | 'Hello, liu' 20 | >>> hello(111) 21 | 'Hello, Everybody' 22 | >>> 23 | 24 | 25 | ``` 26 | 27 | 28 | * get() 函数被调用的时候, 先回检查提供的 key 是否存在 29 | 30 | 1. 如果存在,: 返回 key 对应的 value 31 | 32 | 2. 如果不存在: 返回 default 值 33 | 34 | 35 | # 参考 36 | 37 | real python --https://realpython.com/ 38 | 39 | -------------------------------------------------------------------------------- /Python/python小技巧 :快速合并两个字典.md: -------------------------------------------------------------------------------- 1 | Python 3.6.5 2 | 3 | 4 | ```python 5 | 6 | >>> x = {'a': 1, 'b': 2} 7 | >>> y = {'b': 3, 'c': 4} 8 | >>> z = {**x, **y} 9 | >>> z 10 | {'a': 1, 'b': 3, 'c': 4} 11 | 12 | 13 | 14 | >>> z= {**y,**x} 15 | >>> z 16 | {'b': 2, 'c': 4, 'a': 1} 17 | 18 | ``` 19 | 20 | * python 会按照给定的合并顺序 从左到右进行合并 21 | 22 | * 遇到重复的,后者会覆盖前者 23 | 24 | * 字典规模较小 25 | 26 | 27 | ---- 28 | 29 | # 参考 30 | 31 | real python --https://realpython.com/ 32 | 33 | -------------------------------------------------------------------------------- /Python/全局解释器锁(GIL).md: -------------------------------------------------------------------------------- 1 | 本文为 极客时间 景霄老师 的《 python 核心技术与实战》课程 学习笔记 2 | 3 | ---- 4 | 5 | 6 | ## 1. 问题 7 | 8 | Countdown 一个 数字 9 | 10 | 11 | 1. Basic 版本 12 | 13 | ```python 14 | 15 | def count_down(n): 16 | while n > 0 : 17 | n -= 1 18 | 19 | n = 100000000 20 | count_down(n) 21 | 22 | #########结果 ###### 23 | 24 | 25 | executed in 4.80s, 26 | 27 | ``` 28 | 29 | 30 | 2. 双线程版本 31 | 32 | ```python 33 | from threading import Thread 34 | 35 | t1 = Thread(target= count_down, args= [n//2]) 36 | t2 = Thread(target= count_down, args= [n//2]) 37 | t1.start() 38 | t2.start() 39 | t1.join() 40 | t2.join() 41 | 42 | #########结果 ###### 43 | 44 | executed in 4.87s, 45 | 46 | ``` 47 | 48 | 3. 4 线程 49 | 50 | ```python 51 | 52 | from threading import Thread 53 | 54 | t1 = Thread(target= count_down, args= [n//4]) 55 | t2 = Thread(target= count_down, args= [n//4]) 56 | t3 = Thread(target= count_down, args= [n//4]) 57 | t4 = Thread(target= count_down, args= [n//4]) 58 | t1.start() 59 | t2.start() 60 | t3.start() 61 | t4.start() 62 | t1.join() 63 | t2.join() 64 | t3.join() 65 | t4.join() 66 | 67 | #########结果 ###### 68 | executed in 4.93s 69 | 70 | ``` 71 | 72 | * 多线程没有提升运行速度 73 | 74 | 75 | ------ 76 | 77 | ## 2. 为什么引入 GIL 78 | 79 | 1. 每一个 Python 线程, 在 CPython解释器中执行的时候,都会锁住自己的线程,阻止别的线程执行。 80 | 81 | 82 | 2. Cpython 使用计数来管理内存, Python 中创建的实例 的都会有一个引用计数,来记录由多少个指针指向实例,当引用计数为 0 的时候,自动释放内存。 83 | 84 | ```python 85 | >>> import sys 86 | >>> a = [] 87 | >>> b = a 88 | >>> sys.getrefcount(a) 89 | 3 90 | >>> 91 | ``` 92 | 93 | > In the above example, the reference count for the empty list object [] was 3. The list object was referenced by a, b and the argument passed to sys.getrefcount(). 94 | 空列表 [] 的引用计数是3 ,被 a, b 和 作为参数 传递给函数。 如果有两个 Python 线程同时引用了 a, 会造成引用计数的 race condition,引用计数最终可能只增加 1, 当第一个线程结束的时候, 引用计数减少1, 可能导致内存释放的条件, 第二个线程访问 a 的时候, 找不到有效的饿内存 95 | 96 | 3. Cpython 引入 GIL 97 | 98 | * 避免 race condition 99 | 100 | * CPython 使用很多 C语言库, 但是大部分 C语言库 不是原生线程安全的 101 | 102 | 103 | 104 | 105 | --- 106 | 107 | 108 | ## 3. GIL 工作原理 109 | 110 | 111 | ![](https://i.loli.net/2019/07/18/5d301edebbdfe41692.jpg) 112 | 113 | 114 | 1. 每一个线程开始的时候,都会锁住 GIL阻止别的线程执行, 每一个线程执行完,都会释放 GIL,允许别的线程开始使用资源 115 | 116 | > 从release GIL到acquire GIL之间几乎是没有间隙的。所以当其他在其他核心上的线程被唤醒时,大部分情况下主线程已经又再一次获取到GIL了。这个时候被唤醒执行的线程只能白白的浪费CPU时间,看着另一个线程拿着GIL欢快的执行着。然后达到切换时间后进入待调度状态,再被唤醒,再等待,以此往复恶性循环 117 | 118 | 119 | 120 | ![](https://i.loli.net/2019/07/18/5d302362a11c712910.png) 121 | 122 | 123 | 124 | 125 | 上图 是 CPU 密集型运算, 126 | 绿色表示线程正在执行, 红色表示线程被调度唤醒,但是由于没有 GIL 无法执行, 白色表示 IO线程处于等待 127 | GIL的存在导致多线程无法很好的立即多核CPU的并发处理能力。 128 | 129 | 130 | 2. 使用 check_ interval 机制释放 GIL: 每隔一段时间 Python 解释器会强制当前的线程去释放 GIL。 131 | 132 | 3. GIL 在遇到 IO 的时候 自动释放, IO Bound场景下得多线程会得到较好的性能 133 | ---- 134 | 135 | ## 4. Python 的线程安全 136 | 137 | * 虽然 GIL仅允许一个线程运行,但是还有 check_interval 强行抢占线程机制。 138 | 139 | * GIL的设计,主要是为了 Cpython 解释器层面的编写者,而不是 Python 应用者 140 | 141 | * 还是需要 lock 等工具 保证线程安全 142 | 143 | 144 | --- 145 | 146 | ## 5. 如何避免 GIL 147 | 148 | 1. 绕过 Cpython 解释器,(使用其他的。javapython) 目前已经有很多的 Python 库是 C 实现的, 不受 GIL 影响 149 | 150 | 2. 关键性能代码, 使用 C++ 实现 151 | 152 | 3. 使用 Multi-processing 153 | 154 | ```python 155 | 156 | from multiprocessing import Pool 157 | import time 158 | 159 | if __name__ == '__main__': 160 | pool = Pool(processes=2) 161 | r1 = pool.apply_async(count_down, [n//2]) 162 | r2 = pool.apply_async(count_down, [n//2]) 163 | pool.close() 164 | pool.join() 165 | 166 | ###### 结果 ###### 167 | 168 | executed in 2.63s, 169 | 170 | ``` 171 | 172 | 运行时间 减少了 近乎一半,因为调用多进程也需要大量的消耗 173 | 174 | # 参考 175 | 176 | 1. http://cenalulu.github.io/python/gil-in-python/ 177 | 178 | 2. https://juejin.im/post/5ce1707df265da1ba431be19 179 | 180 | 3. What is the Python Global Interpreter Lock (GIL)? --https://realpython.com/python-gil/ 181 | 182 | 4. https://www.youtube.com/watch?v=Obt-vMVdM8s&feature=youtu.be 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/.DS_Store -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/AutoEncoder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/AutoEncoder.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/README.md: -------------------------------------------------------------------------------- 1 | # 图集 2 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/RNN--Using.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/RNN--Using.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/SVD++.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/SVD++.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/Word2vec 预测.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/Word2vec 预测.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/YouTube-神经网络.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/YouTube-神经网络.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/偏置信息的SVD、.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/偏置信息的SVD、.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/内容推荐总结.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/内容推荐总结.jpg -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/内容推荐的框架图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/内容推荐的框架图.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/卡方检验.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/卡方检验.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/开源-内容分析、.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/开源-内容分析、.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/开源-协同过滤+矩阵分解.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/开源-协同过滤+矩阵分解.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/开源-混合模型.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/开源-混合模型.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/开源项目-推荐系统.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/开源项目-推荐系统.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/循环神经网络.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/循环神经网络.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/损失函数定义.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/损失函数定义.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/推荐系统_概念篇.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/推荐系统_概念篇.jpg -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/推荐计算公式.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/推荐计算公式.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/深度学习总结.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/深度学习总结.jpg -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/皮尔逊相关.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/皮尔逊相关.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/矩阵--神经网络.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/矩阵--神经网络.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/矩阵分解总结.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/矩阵分解总结.jpg -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/置信度+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/置信度+.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Image/近邻推荐总结.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Image/近邻推荐总结.jpg -------------------------------------------------------------------------------- /Recommendation_Agorithm/Papers_Learning/README.md: -------------------------------------------------------------------------------- 1 | # 相关文献阅读 2 | 3 | # 1. Deep Learning based Recommender System: A Survey and New Perspectives -- 2017 4 | 5 | * Deep learning is able to effectively capture the non-linear and non-trivial user-item relationships, and enable the codification of more complex abstractions as data representations in the higher layers. Furthermore, it catches the intricate relationships within the data itself, from abundant accessible data sources such as contextual, textual and visual information. 6 | 7 | ### 1. Multilayer Perceptron based Recommender System 8 | 9 | 10 | ##### 1. 传统的 矩阵分解 11 | 12 | * MF模型是用户和项目的潜在因素的双向互动,它假设潜在空间的每一维都是相互独立的并且用相同的权重将它们线性结合。因此,MF可视为隐向量(latent factor)的线性模型。 13 | 14 | 15 | 16 | * 使用一个简单的和固定的内积,来估计在低维潜在空间中用户-项目的复杂交互,从而所可能造成的限制 17 | 18 | 19 | ##### 2. NCF 模型--- NLP 20 | 21 | * 用户和商品 分别 embedding 生成向量 22 | 23 | * concat 两个向量 24 | 25 | * 输入 多层神经网络 26 | 27 | * 目标函数 : 将 yui 的值作为一个标签——1表示项目 i 和用户 u 相关,否则为0。这样,预测分数 ŷ ui 就代表了项目 i 和用户 u 相关的可能性大小。因此,我们需要将网络输出限制到[0,1]的范围内。 28 | 29 | 30 | 31 | ##### 3. wide and deeplearning ----> Deep FM 32 | 33 | * DeepFM包含两部分:神经网络部分与因子分解机部分,分别负责低阶特征的提取和高阶特征的提取。这两部分共享同样的输入, 34 | 35 | 36 | 37 | 38 | ------- 39 | 40 | 41 | ### 2. Autoencoder based Recommender System 42 | 43 | ##### 1. AutoRec 44 | 45 | * I-AutoRec performs better than U-AutoRec, which may be due to the higher variance of user partial observed vectors. 46 | * Different combination of activation functions f (·) and д(·) will influence the performance considerably. 47 | * Increasing the hidden unit size moderately will improve the result as expanding the hidden layer dimensionality gives AutoRec more capacity to model the characteristics of the input. 48 | * Adding more layers to formulate a deep network further improves the performance. 49 | 50 | 51 | ##### 2. CFN -- Collaborative Filtering Neural network 52 | 53 | * 加入了去噪声的机制, 模型更加鲁棒 54 | * 加入 side-information : 例如 个人信息,商品描述 55 | 56 | 57 | ##### 3. CDAE(Collaborative Denoising Auto-Encoder) --- ranking Prediciton 58 | 59 | * Parameters are learned by minimizing the reconstruction error: 60 | 61 | * 加入负样本,在隐式反馈中, 加快计算速度,减少计算的复杂度。 62 | 63 | [YaoWu,ChristopherDuBois,AliceXZheng,andMartinEster.2016.Collaborativedenoisingauto-encodersfortop-nrecommender 64 | systems. In Proceedings of the Ninth ACM International Conference on Web Search and Data Mining. ACM, 153–162.]() 65 | 66 | 67 | 68 | ----- 69 | 70 | ### 3. Convolutional Neural Network based Recommender System 71 | 72 | ##### 1. BCNN 73 | 74 | 75 | 76 | ##### 2. ABCNN(Attention based CNN.) 77 | 78 | 79 | 80 | 81 | ---- 82 | 83 | 84 | ### 4. Recurrent Neural Network based Recommender System 85 | 86 | ##### 1. Session-based recommendation 87 | 88 | > 服务端为特定的对象创建了特定的Session,用于标识这个对象,并且跟踪用户的浏览点击行为。我们这里可以将其理解为具有时序关系的一些记录序列。 89 | 90 | 91 | * 基于内容的推荐算法和协同过滤推荐算法(model-based、memory-based)在刻画序列数据中存在缺陷:每个item相互独立,不能建模session中item的连续偏好信息。 92 | 93 | * 1. item-to-item recommendation approach (Sarwar et al.,2001; Linden et al., 2003) : 采用session中item间的相似性预测下一个item。缺点:只考虑了最后一次的click 的item相似性, 忽视了前面的的clicks, 没有考虑整个序列信息。 94 | 95 | * 2. Markov decision Processes (MDPs)(Shani et al., 2002):马尔科夫决策过程,用四元组(S: 状态, A: 动作, P: 转移概率, R: 奖励函数)刻画序列信息,通过状态转移概率的计算点击下一个动作:即点击item的概率。缺点:状态的数量巨大,会随问题维度指数增加。 96 | 97 | 98 | 99 | 100 | ------------- 101 | ------------ 102 | 103 | # 2. Session-based recommendations with recurrent neural networks. (ICLR 2016) 104 | 105 | ### 1. 模型(GRU4REC)架构(如下图) 106 | 107 | * 模型输入: session 中的点击序列, x = [x_{1},x_{2}...x_{r-1},x_{r}] , 1 ≤ r < n,通过one hot encoding 编码,通过embedding层压缩为低维连续向量作为 GRU 的输入。 108 | 109 | * 模型输出:每一个item 被点击的预测概率, y =M(x), where y = [y_{1},y_{2}...y_{m}] 110 | 111 | 112 | ### 2. Training data sample: 113 | 114 | * 因为item的维度非常高,item数量过大的概率会导致计算量庞大,所以只选取当前的正样本(即下一个点击的item)加上随机抽取的负样本。论文采用了取巧的方法来减少采样需要的计算量,即选取了同一个mini-batch 中其他sequence下一个点击的item作为负样本,用这些正负样本来训练整个神经网络。 115 | 116 | 117 | ### 3. 损失函数 118 | 119 | * Pairwise ranking,即正样本的loss要低于负样本。本文使用了两种基于Pairwise ranking的loss function: 120 | 121 | * BPR:一种矩阵分解法, 122 | 123 | * TOP1:一种正则估计 124 | 125 | 126 | 127 | ----------- 128 | ---------- 129 | 130 | # 3. Incorporating Dwell Time in Session-Based Recommendations with Recurrent Neural Networks. (RecSys 2017) 131 | 132 | **用户在session中的item停留时间越长,越感兴趣** 133 | 134 | 135 | * 每个item 按照单位时间划分成 d_{t_{i}}/t+1个时间片 136 | 137 | 138 | 139 | ------- 140 | -------- 141 | 142 | # 4. Improved Recurrent Neural Networks for Session-based Recommendations. (DLRS 2016) 143 | 144 | ### 1. Data augmentation(数据增强) 145 | 146 | * 给定一个session的输入序列 [x_{1},x_{2}...x_{n}] , 可以产生多条训练数据,如( [x_{1},V(x_{2})], [x_{1},x_{2}, V(x_{3})] )如下图,可以增加训练数据。此外,用户可能出现误点击的,用dropout 的方式来泛化数据,可以增强训练的鲁棒性。 147 | 148 | 149 | ### 2. Model pre-training 150 | 151 | * 在推荐中,对于user和item更新都很快的推荐场景,最近的信息更为重要,文本提出先利用历史所有数据预训练出一个模型,然后只选取最近的数据,以预训练得到的模型权重作为初始化参数,再训练一个最终模型。 152 | 153 | 154 | ### 3. Output embedding 155 | 156 | * 直接预测 item 的 embedding 向量。使预测结果更具有泛化意义,相当于预测了用户 embedding后的语义空间中兴趣表示,训练时定义的loss为输出层与该样本在embedding层的cosine相似度。 157 | 158 | 159 | 160 | ------ 161 | ------ 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/.DS_Store -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_1.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_apploication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_apploication.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_dataset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_dataset.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_techs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_techs.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_可解释性1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_可解释性1.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题2.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuChuang0059/Basic-Knowledge-of-Computer-Science/3bd6eda27d60759c1ef7b9278fc66c6dd95e1eb3/Recommendation_Agorithm/Recsys2018_Summary/Image/re_新问题3.png -------------------------------------------------------------------------------- /Recommendation_Agorithm/排行榜.md: -------------------------------------------------------------------------------- 1 | # 1. Ranking 2 | 3 | * Popularity is the obvious baseline + Many other features can be added 4 | 5 | 6 | * Quality of ranking measured using metrics--指标衡量 7 | > 但是难以用这些指标 优化机器学习模型 8 | * Normalized Discounted Cumulative Gain 9 | * Mean Reciprocal Rank (MRR) 10 | * Fraction of Concordant Pairs (FCP) 11 | 12 | 13 | * Approaches 14 | * Point wise --- 逐点的 15 | * Ranking function minimizes loss function defined on individual relevance judgment 16 | * Logistic regression, SVM, GBDT 17 | 18 | * Pairwise 19 | * Loss function is defined on pair-wise preferences 20 | * minimize number of inversions in ranking-----两两一对,目标就是减少 反序的数量 21 | * RankSVM, RankBoost, RankNet, FRank... 22 | 23 | * Listwise 24 | * Indirect loss function 25 | * RankCosine: similarity between ranking list and ground truthas loss function 26 | * ListNet: KL-divergence as loss function by defining aprobability distribution 27 | * Problem: optimization of listwise loss function may not optimizeIR metrics 28 | 29 | * Directly optimizing IR metric (difficult since they arenot differentiable) 30 | − Genetic Programming or Simulated Annealing 31 | 32 | − LambdaMart weights pairwise errors in RankNet by IR metric 33 | 34 | − Gradient descent on smoothed version of objective function (e.g. CLiMF or TFMAP) 35 | 36 | − SVM-MAP relaxes MAP metric by adding to SVM constraints 37 | 38 | − AdaRank uses boosting to optimize NDCG 39 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/推荐系统_概念.md: -------------------------------------------------------------------------------- 1 | # 推荐系统概念 2 | 3 | 4 | # 1. Define 推荐系统 5 | 6 | * 推荐系统可以把那些最终会在用户(User)和物品(Item)之间的连接提前找出来 7 | > 人和人之间的社会连接,人和商品的消费连接,人和咨询之间的阅读连接 8 | 万物互联形成大网 , 节点: 人 和 其他 ; 为人建立连接是要义 9 | 10 | * 推荐系统需要已经存在的连接,去预测 11 | 12 | ----- 13 | 14 | # 2. 是否需要推荐系统 15 | 16 | * 是否需要建立的连接越多越好 17 | * 产品现有的连接---连接数量的瓶颈取决于物品的数量 18 | * 产品数量少 19 | * 用户回村访问很低--- 长尾理论 20 | > 如果增加的连接数主要靠增加的活跃用户数和增加的物品数贡献, 不适合推荐系统 21 | 反之 说明连接数目已经有自发生长的趋势,适合 22 | 23 | * 数据导向的产品文化 24 | 25 | 26 | --- 27 | # 3. 推荐系统的问题模式 28 | 29 | * 评分预测 30 | * 行为预测 31 | > 对推荐结果的两类反馈, 32 | 33 | ## 1. 评分预测 --- 显示反馈 34 | > 消费完物品会给出一个打分,提前预测分数 35 | 36 | * 预测分数和实际分数之间会有误差,根据误差调整模型的参数,----回归问题 37 | > Netflix 的评判标准-- RMSE : 均方根误差 38 | 39 | * 评分类存在的问题 40 | * 数据不易收集 41 | * 数据质量不能保证 42 | * 评分的分布不稳定, 差别较大 43 | 44 | ## 2. 行为预测---隐式反馈 45 | * 直接预测行为本身的概率,预测商品的相对排序------CTR 预估(点击率) 46 | > 推荐后是否会点击进行二分类,建立分类模型,预估一种分类的概率 47 | 48 | * Pros: 49 | > 1. 数据比显式反馈更加稠密。诚然,评分数据总体来说是很稀疏的,之前netflix的百万美元挑战赛给出的数据稀疏度大概是1.2%,毕竟评分数据是要消耗更多注意力的数据。 50 | > 2. 隐式反馈更代表用户的真实想法,比如你不是很赞成川普的观点,但是还是想经常看到他的内容(以便吐槽他),这是显式反馈无法捕捉的。而人们在Quora上投出一些赞成票也许只是为了鼓励一下作者,或者表达一些作者的同情,甚至只是因为政治正确而投,实际上对内容很难说真正感兴趣。 51 | > 3. 隐式反馈常常和模型的目标函数关联更密切,也因此通常更容易在AB测试中和测试指标挂钩。这个好理解,比如CTR预估当然关注的是点击这个隐式反馈。 52 | 53 | 54 | ----- 55 | 56 | # 4. 推荐系统常见的问题 57 | 58 | ### 1. 冷启动问题 59 | 60 | * 新用户或者新物品的展示较少,想办法引入数据。 61 | 62 | ### 2. 探索和利用问题-- EE 63 | * 对用户身上已经探明的兴趣加以利用,探明用户身上还不知道的兴趣 64 | 65 | ### 3. 安全问题 66 | 67 | ----- 68 | 69 | # 5. 推荐系统的关键性元素 70 | 71 | * UI 和 UE 72 | * 数据 73 | * 领域知识---- 74 | * 算法 75 | 76 | 77 | 传统软件: 信息流通管道,追求稳定, 78 | 79 | 推荐系统:信息过滤工具,追求的是指标的增长---量化 80 | * 以概率的眼光和思想看待问题 81 | 82 | 83 | 84 | ---------- 85 | 86 | # 总结 87 | 88 |

89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/深度学习--推荐系统.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | 5 | 6 | 7 | 8 | ------- 9 | 10 | # 1. 矩阵分解 ---> 浅层神经网络 11 | 12 | 13 |

14 | 15 | 1. 用户 UI 评分过的物品有 I2 和 I4 16 | 17 | 2. UI 的 隐因子向量 [W1,W2], 物品2 的隐因子向量是 [W3, W5]; 物品 I4 的隐因子向量[W4, w6] 18 | 19 | 3. 矩阵分解看作是一个拥有一个隐藏层的神经网络,得到的隐因子向量就是神经网络的连接权重 20 | 21 | **本质属性的挖掘** 22 | 23 | 1. 更加高效而且真实的反映事物本身样子。 24 | > 图片使用原始的像素点表示,占用空间大,不能反映图片更高级的特征,线条,明暗,色彩(使用CNN学习) 25 | 26 | 2. 更加真实的反映出用户和物品之间的连接。 使用物品背后的隐藏因子表示用户的兴趣,更高效更真实。考虑来物品本身的相似性,信息都压缩到隐因子向量中,同时再得到物品的隐因子向量, 27 | 更加直接平滑的算出用户对物品的偏好程度 28 | 29 | 30 | **深度学习-- 推荐系统** 31 | 32 | * Embedding : 矩阵分解, Word2vec 33 | 34 | * Predicting: 深度神经网络的CTR 预估,深度协同过滤,时间序列的深度模型 35 | 36 | 37 | -------- 38 | 39 | 40 | # 2vec (word2vec - Sentence2vec - Doc2vec) 41 | 42 | ## 1. Word2vec 学习词嵌入向量,把一个词表示成一个稠密的向量,计算词的相似度 43 | 44 | 45 | ### 1. 类似于CNN的方法 46 | 47 | 1. 使用滑动窗口,在一篇文档中从左向右滑动,每次都有N个词在窗口内, 每移动一下,都产生 N-1 个样本 48 | 49 | 2. 每条样本都是使用窗口内的每一个词 去预测窗口正中央的词, 50 | 51 | 52 |

53 | 54 | 55 | 56 | * 输入特征是词的嵌入向量,预测标签是 窗口中心的那个词 57 | 58 | * 实际上,输入时候每个词 使用One-hot 表示成一个向量,向量的长度是整个词表的长度,当前词的位置是1 ,其他的是 0 59 | 60 | 61 | **输入层和隐藏层之间的连接权重就是 最终的嵌入向量的元素值** 62 | 63 | 64 | ------ 65 | 66 | ### 2. 逆向的CNN 67 | **交换输入和输出** 68 | 69 | 使用窗口中央的词去预测周围的词 70 | 71 | **核心不是为了预测词,而是为了得到词的嵌入向量** 72 | 73 | ------- 74 | 75 | 76 | 77 | ## 2. Sentence2Vec 78 | 79 | 将包含的词的嵌入向量累加起来 80 | 81 | 82 | ---- 83 | 84 | ## 3. Doc2vec -- ?? 85 | 86 | 创建N-1 条样本的时候,还增加一条样本, 段落ID的预测中央的那个词 87 | 88 | --- 89 | 90 | 91 | ### 4. Product2vec 92 | 93 | 将用户按照时间先后顺序加入到购物车的商品,看成一个一个的词,所有的商品看成是一个文档 94 | 95 | ---- 96 | 97 | # 3. AutoEncoder -- 自动编码器(受限玻尔兹曼机) 98 | 99 | 输入和输出一样的神经网络,目的是更加清楚的认识自己,学习到的网络的连接权重都是不同的嵌入向量 100 | 101 | 1. 输入数据逐层降维,对原始数据开始编码,之后逐层增加神经元,相当于解码, 102 | 103 | 2. 解码的输出要和原始数据越接近越好 104 | 105 | 3. 大幅度的压缩原始特征空间的同时,压缩损失越小越好 106 | 107 | 108 |

109 | 110 | 111 | ------ 112 | 113 | # 4. YouTube 推荐排序模型 114 | 115 |

116 | 117 | 118 | 119 | * 模型训练的时候,softmax 作为输出层, 120 | * 实际线上预测服务的时候,模型关心相对顺序, 使用用户的特征向量做近似的近邻搜索,生成最相近的一些推荐结果 121 | 122 | 123 | 124 | ---- 125 | # 5. 时间属性 126 | 127 | 128 | 时间属性---用户操作行为的先后顺序 129 | 130 | 131 | **循环神经网络** 132 | 133 |

134 | 135 | 136 | 137 | 1. 隐藏层的输入不仅是输入层 xt ,还有时刻 t-1 的隐藏层输出 138 | 139 | 2. 现在 时刻的信息 不只和现在的输入有关,还和上一个时刻的状态有关 140 | 141 | 142 | 143 | 144 | ------------ 145 | 146 | # 6. Spotify 使用 RNN 进行个性化的播单生成 147 | 148 | > 使用循环神经网络, 把音乐播单的生成看成是歌曲时间序列的生成,歌曲得到不但受用户当前的特征影响,还受上一首歌的影 149 | 150 | 151 | ------- 152 | 153 | 154 | 155 | 156 |

157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/矩阵分解.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | 5 | 6 | 7 | 8 | 9 | 10 | # 1. 为什么使用矩阵分解 11 | 12 | 近邻模型的问题: 13 | 14 | 1. 物品之间存在相关性,信息量并不随着向量的纬度增加而 线性增加;??? 15 | 2. 矩阵元素稀疏,计算结果不稳定,增加一个向量纬度,导致近邻结果差异很大 16 | 17 | # 2. SVD算法 18 | 19 | ## 1. 基础的SVD算法 20 | 21 | 1. 将用户和物品都映射到一个 k 维空间,k 维空间不一定具有很好的解释性,维度成为隐因子 22 | 23 | 2. 用户向量 p , 代表用户在若干因素的偏好(k); 对于物品向量 q :物品 背后暗藏的一些用户关注的因素 24 | 25 | 3. 用户的向量是pu 物品的向量是qi 物品推荐给用户的推荐分数是 二者的点积 26 | 27 | 4. 计算 k 维向量 --- k 由 K-fold确定 28 | * 损失函数 29 | * 优化算法 30 | 31 |

32 | 33 | * 前部分 计算预测误差 34 | * 后部分,减小隐因子的向量,控制模型的方差-------- 正则化 35 | 36 | 5. 整体的学习过程 37 | 38 | * 评分数据 39 | * 分解矩阵,随机初始化元素 40 | * 利用矩阵预测 ,计算误差函数 41 | * 梯度下降,确定矩阵的元素值 42 | 43 | 44 | ------- 45 | 46 | ## 2. 增加偏置信息 47 | 48 | > 避免一些 偏高的 评分 49 | 50 | **抽取偏置信息的SVD** 51 | 52 | 评分会由四部分相加 = 全局平均分, 物品的评分偏置(与平均分的比较),用户评分偏置(与平均分的比较) ,用户和物品之间的兴趣偏好(点积) 53 | 54 | 55 |

56 | 57 | 58 | 59 | 60 | ----- 61 | 62 | ## 3. 增加历史信息 63 | 64 | 结合 用户的隐式反馈和属性---SVD++ 65 | 66 | * 假设评分矩阵中的物品有一个隐因子向量, 67 | * 用户行为的物品集合 也有一个隐因子向量,纬度相同---- 操作过的物品的隐因子向量加起来,表达用户的兴趣偏好 68 | 69 | * 对于用户属性,全部转化成 0,1 特征后, 提取同样纬度的隐因子向量,所有属性的隐因子向量相加和,表达用户的兴趣偏好 70 | 71 | 用户向量增加用户属性向量 和 隐式反馈向量 72 | 73 |

74 | 75 | -------- 76 | 77 | ## 4. 考虑时间因素 78 | 79 | 1. 对评分按照时间加权,久远的评分更趋近于平均值 80 | 81 | 2. 对评分时间划分区间,不同的时间区间内学习出的隐因子向量,使用按照区间的对应的隐因子向量来计算 82 | 83 | 3. 特殊的期间, 节日,周末等训练对应的隐因子向量 84 | 85 | ------------ 86 | 87 | # 3. 交替最小二乘(ALS) 88 | 89 | 1. 随机初始化 Q, 线性代数,求解 逆矩阵 P 90 | 91 | 2. 将 P 看作 已知的,,利用误差函数,优化参数 求解出Q 92 | 93 | 3. 交替进行,满足误差阈值 94 | 95 | 96 | Pros: 不是很稀疏的矩阵上,ALS 效果更好一点 97 | 98 | 99 | ------- 100 | 101 | # 4. 隐式反馈 102 | 103 | 行为预测模型: One - Class数据 104 | 105 | > 预测用户行为看作是一个 二分类的问题, 猜测用户会不会去做某事,但是实际上收集的数据只有明确的一类: 用户做了某事,而用户不做某事的数据没有表达 106 | 107 | 隐式反馈的矩阵分解--- Weight- ALS 加权交替最小二乘 108 | 109 | 110 | 111 | * 行为的次数是 对行为置信度的反应,即是 所谓的加权 112 | * 用户对物品无隐式反馈 则认为评分是 0; 113 | * 用户对物品至少有一次隐式反馈 则认为评分是1 ; 次数作为评分的置信度 114 | 115 |

116 | 117 | 其中置信度 Cui = 1 + a* C (C 是次数,a是超参数,默认取值40 ) 118 | 119 | 120 | **问题** 121 | 122 | 没有反馈的缺失值,设定为0 ,这样会导致取值为0 的评分非常多,政府样本非常不平衡,严重倾斜到 0 评分的一边 123 | 124 | 目的就是填充缺失值,所以不应该全部是 0 125 | 126 | 127 | **Solve** 128 | 129 | 按照物品的热门程度进行填充 130 | > 什么样的适合选作负样本,----> 展示给用户,用户意识到存在,但是没有反馈。,,但是 问题是不知道用户有没有意识到物品的存在, 131 | 因此,按照物品的热门程度来的话,越热门,用户越可能知道他的存在,这种情况,还是没有反馈,这是真正的负样本 132 | 133 | ----- 134 | 135 | 136 | 137 | # 5. 推荐计算 138 | 139 | * 得到 用户的隐因子向量(稠密向量) --代表兴趣 140 | * 物品的 稠密向量,代表他的语义或者主题 141 | 142 | **解决计算复杂度** 143 | 144 | * 专门设计数据结构储存所有物品的隐因子向量,一个用户返回最近似的k个物品 145 | 开源 Faiss ,Annoy ,Kgraph ,NMSLIB 146 | > 动态增加 物品向量 --Faiss ;; 不是的话: NMSLIB 或者 Kgraph 147 | 148 | * 物品的隐因子向量先做聚类分析,再逐一计算用户和每个聚类中心的推荐分数,给用户推荐物品聚类 149 | 得到推荐的聚类后,, 再从每个聚类中挑选少许的几个物品作为推荐结果 150 | 151 | ------- 152 | 153 | # 6. 矩阵分解的不足 154 | 155 | 156 | ## 1. Point-Wise 157 | > 只单独考虑每个物品,每个物品像是空间中孤立的点一样。 158 | 只能收集正样本,没有负样本,认为缺失值就是负样本,再以预测误差来逼近这些样本 159 | 160 | 161 | 162 | ## 2. pair-wise 163 | > 直接预测物品两两之间相对顺序的问题 164 | 165 | 166 | ------ 167 | 168 | # 7. 贝叶斯个性化排序 169 | 170 | 1. 关注相对的排序 -- 使用AUC(Area Under Curve) 作为评价指标 ----曲线下的面积(ROC曲线) 171 | 172 | 2. AUC 等价于: 模型把关心的那一类样本排在其他样本前面的概率,最大是1 ,0.5 就是随机排列 173 | 174 | 175 | 3. BPR 具体 176 | 177 | ### 1. 构造样本 178 | BPR 关心的是 物品之间相对用户的相对顺序,样本(用户,物品1,物品2 ,两个物品的相对顺序) 179 | 180 | * 物品1 是消费过的,2 不是 相对顺序取值为1 , 是正样本 181 | * 如果相反, 则是负样本 182 | * 样本中不包含其他情况: 都消费过或者都没消费过 183 | 184 | 学习的数据是反应用户偏好的相对顺序,使用的时候,面对的是所有用户还没消费过的物品,这些物品荏苒可以在这样的模型下得到相对的顺序??? 185 | 186 | ### 2. 目标函数 187 | 188 | 1. 最大化交叉熵--目标函数 189 | 2, 防止过拟合,加入正则项---- 认为模型参数有个先验的概率, 190 | 191 | 3. BPR 认为模型的先验概率符合正态分布 192 | 193 | 194 | ### 3. 训练方法 195 | 196 | * 批量梯度下降 --- 收敛慢 197 | * 随机梯度下降 --- 训练快 却不稳定 198 | 199 | * 重复抽样的梯度下降 200 | 1. 全样本随机抽取一部分样本 201 | 2. 使用这部分样本 SGD 更新参数模型 202 | 3. 重复 203 | 204 | 205 | -------- 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | -------------------------------------------------------------------------------- /Recommendation_Agorithm/近邻推荐-协同过滤.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | 6 | 7 | 8 | ---------- 9 | # 1. 协同过滤 10 | > 协同过滤的核心是用户物品关系矩阵 11 | 12 | * 基于记忆的协同过滤 13 | > 记住消费过的物品,推荐相似的东西,或者推荐相似的人的消费的东西 14 | 15 | * 基于模型的协同过滤 16 | > 从用户物品关系矩阵中学习一个模型,从而把矩阵的空白处填满 17 | 18 | 19 | ------- 20 | 21 | 22 | # 2. 基于用户的协同过滤 23 | 24 | * 1. 准备用户向量 25 | * 向量的纬度是物品的数量 26 | 27 | * 2. 使用用户向量,计算两两用户之间的相似度,设定一个相似度阈值, 28 | 29 | * 3. 为每一个用户产生推荐结果 30 | > 聚类相似的用户喜欢的用品汇总起来,去掉用户已经消费过的物品,剩下的排序 就是推荐结果 31 | 32 | 计算公式: 33 | 34 | 35 |

36 | 37 | * P 是计算每一个物品 和用户之间的匹配分数 38 | 39 | * 分母是 把和用户u相似的n个用户的相似度加起来 40 | 41 | * 分子 是: n 个用户对商品的态度 按照相似度加权平均。 42 | 43 | 44 | 45 | 46 | 47 | ### 1. 构造矩阵 48 | 49 | 协同过滤计算,使用的矩阵是稀疏的,稀疏矩阵的典型储存格式 50 | 51 | * CSR 整体编码 = 数值 列号 行偏移 52 | * COO 每个元素使用三元组表示 (行号,列号,数值) 53 | 54 | ### 2. 相似度计算 55 | 56 | 1. 向量很长--降低计算复杂度 57 | 58 | * 对向量采样计算--- Twitter : DIMSUM算法 ;在Spark中实现 59 | 60 | * 向量话计算 : 避免循环,转换成向量 61 | 62 | 63 | 2. 用户量很大,两两之间的计算代价很大 64 | 65 | * 相似度计算拆分成 Map Reduce 任务,将原始矩阵成建为 用户对, 值为两个用户对同一个物品分评分之积 66 | 67 | * 数据量不超过百万,矩阵稀疏, 单机工具: KGraph, GraphCHI 68 | 69 | 70 | 71 | ### 3. 推荐计算 72 | 73 | **计算过程拆分成Map Reduce 任务**--- 使用多线程技术实现Map的效果: C++ 的 OpenMP 库,使用多线程。 74 | 75 | 具体拆分: 76 | 77 | * 1. 遍历每个用户喜欢的物品列表 78 | 79 | * 2. 获取该 用户的相似性用户列表 80 | 81 | * 3. 把每一个喜欢的物品 Map 成两个记录发射出去,一个是键为 < 相似用户 ID,物品 ID,1> 三元组,可以拼成一个字符串,值为 < 相似度 >, 82 | 另一个是键为 < 相似用户 ID,物品 ID,0> 三元组,值为 < 喜欢程度 * 相似度 >,其中的 1 和 0 为了区分两者 83 | 84 | * 4. Reduce 阶段,求和后输出; 85 | 86 | * 5. < 相似用户 ID,物品 ID, 0> 的值除以 < 相似用户 ID,物品 ID, 1> 的值 87 | 88 | 89 | ### 4. 改进 90 | 91 | > 改进集中在 用户对物品的喜欢程度上 92 | 93 | * 惩罚对热门物品的喜欢程度, 热门的东西很难反应用户端额真是兴趣,无聊随便点击,群体行为常见特点 94 | 95 | * 增加喜欢程度的时间衰减,使用一个指数函数,指数是一个负数 96 | 97 | ------ 98 | 99 | 100 | # 3. 基于物品的协同过滤 101 | 102 | 1. 物品的数量少于用户的数量; 103 | 104 | 2. 物品之间的相似度 静态,变化的速度没有用户的口味变化快 105 | 106 | 3. 计算物品之间相似度稀疏度是好过计算用户之间的相似度的 107 | 108 | 109 | * 计算步骤 110 | 111 | 1. 构建用户物品的关系矩阵, : 用户的消费行为,消费后的评价,消费行为的量化: 时间,次数,费用 112 | 113 | 2. 计算得到物品相似度的矩阵 114 | 115 | 3. 产生推荐结果 116 | 117 | 118 | 119 | ### 1. 计算物品之间的相似度 120 | 121 | 122 | * 物品向量: 稀疏向量,纬度是用户, 各个纬度的取值是,对这个物品的消费结果,行为本身的布尔值 123 | 124 | * 两两计算物品的相似度 : 余弦相似度 125 | 126 | 127 | 改进物品之间的相似度 128 | 129 | * 物品中心化, 130 | > 计算 每一个物品收到的评分的平均值,物品向量中的分数减去对应物品的均值。(去掉物品中铁杆粉丝群体的非理性因素) 131 | 132 | * 用户中心化 133 | > 计算每一个用户的评分均值,打过的所有分数都减去这个均值 134 | 135 | 136 | ### 2. 计算推荐结果 137 | 138 | #### 1. TopK 推荐--- 猜你喜欢 139 | 140 | > 汇总和用户已经消费过的物品的相似物品----- 使用相似度加权汇总 (按照用户评分过的物品,逐一取出和他们相似的物品) 141 | 142 | 143 | #### 2. 相关推荐 --- 类似于 ”看了又看“ 144 | 145 | **Slope One算法** --- 解决评分矩阵 146 | 实时更新 ??? 147 | 148 | 149 | 150 | 151 | 152 | ------- 153 | 154 | 155 | # 4. 相似度计算方法 156 | 157 | ### 1. 欧式距离 158 | 159 | * 坐标向量之差 160 | * 因为得到的值是正的 很大 ,需要二次转化 (➕1后取倒数)--- 转化为0-1 161 | 162 | > 用于分析用户能力模型之间的差异 163 | 164 | ------ 165 | 166 | ### 2. 余弦相似度 167 | 168 | 余弦相似度的计算 与向量的长度无关---- 计算对向量的长度进行归一化 169 | **思想: 两个向量,只要方向一直,无论程度强弱,都可以视作 相似** 170 | > 例如: 140字的微博摘要了一篇5000字的博客内容,文本向量认为方向一致,词频程度不同,(检查重复--缩写摘要论文) 171 | 172 | 173 | 对绝对值大小不敏感--问题 174 | > A 对两部电影的评分 1,2 B对两部电影的评分 4,5 余弦相似度极速哪出来,相似度 98% 不符合 175 | 176 | **改进-- 调整的余弦相似度** 177 | 178 | 先计算向量每个纬度上的均值向量各个纬度上减去均值 179 | 180 | 181 | ------ 182 | 183 | ### 3. 皮尔逊相关度 184 | 185 |

186 | 187 | 188 | 189 | 皮尔逊相关计算的是两个变量变化的趋势是否一致 190 | 191 | 192 | ------- 193 | 194 | ### 4. jaccard 相似度 --- 适合布尔向量 195 | 196 | 两个集合的交集元素的个数在并集中所占的比例 197 | 198 | * 分子是两个布尔向量做点积运算--- 交集元素的个数 199 | * 分母是 两个布尔向量做 或的运算, 求和 200 | 201 | **适用于隐式反馈:计算用户的收藏行为** 202 | 203 | 204 | ------- 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 |

213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /Techs/GitHub使用技巧.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GitHub 使用技巧 3 | tags: 4 | - Tech 5 | - Github 6 | categories: 7 | - Tech 8 | toc: true 9 | 10 | --- 11 | 12 | 13 | 14 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/ruu1q.jpg) 15 | 16 | 17 | Num | Tip 18 | ---- | --- 19 | 2 | 访问html文件 20 | 3 | 调整GitHub图片格式 --- 图片的大小,位置,一行摆放几个 👍 21 | 4 | 自动生成目录 [TOC] 22 | 5 | GitHub-markdown 添加 latex 公式,显示 Latex 23 | 6 | Github 绘制表格--踩坑 24 | 25 | 26 | 27 | 28 | # 2 访问 html 文件 29 | 30 | 在 github 上面 html 的链接前面添加上https://htmlpreview.github.io/? 31 | 32 | 33 | * 比如这个链接https://github.com/ruanyf/jstraining/blob/master/demos/backbone-demo/index.html 34 | 35 | * 你打开看到的是 html 页面, 36 | 37 | * 加上https://htmlpreview.github.io/? 之后就可以直接显示网页了,如下 38 | https://htmlpreview.github.io/?https://github.com/ruanyf/jstraining/blob/master/demos/backbone-demo/index.html 39 | 40 | 41 | 42 | 43 | ---------- 44 | # 3 调整 GitHub 图片格式 45 | 46 | ## 1. 加上适当的空格 47 | * 在中文和英文数字之间加上空格可以大大提高文档的可读性。 48 | 49 | 50 | ## 2. 图片引用转换 51 | * Markdown 文档可以使用 `![]()` 这种方式来引用图片,但是无法设置大小,只有 `` 才支持设置大小。 52 | 过大的图片会造成文档内容过于粗糙,图片大小的选取以图片内的文字和文档文字大约一致为宜。 53 | 54 | * 图片居中显示可以使得文档阅读体验更好,因此除了将图片引用转换为 img 标签之外,也会将图片居中显示:`

` 55 | 56 | * 工具链接---https://cyc2018.github.io/Text-Typesetting/ 57 | 58 | * 或者直接`

` 59 | 60 | ## 参考---https://github.com/CyC2018/Text-Typesetting 61 | --------------------- 62 | 63 | 64 | 65 | # 4 自动生成目录 66 | 67 | 68 | ## 1. 安装 69 | * 1.安装 homebrew 70 | 71 | * 2.利用 homebrew 安装 wget 72 | 73 | ``` 74 | brew search wget 75 | brew install wget 76 | ``` 77 | 78 | * 3.安装 toc 79 | 80 | ``` 81 | $ wget https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc 82 | $ chmod a+x gh-md-toc 83 | ``` 84 | 85 | ## 2. 使用 86 | 87 | ### 1. 直接网页--效果不好 88 | ``` 89 | ./gh-md-toc https://github.com/ekalinin/envirius/blob/master/README.md 90 | 91 | ``` 92 | 93 | ### 2. 下载本地 ----有少量错误,需要微调。 94 | 95 | 1. readme 文件下载到 gh-md-toc目录 96 | 97 | 2. 在文件路径执行代码 98 | 99 | ``` 100 | ./gh-md-toc README.md 101 | ``` 102 | 103 | 3. 生成的目录代码拷贝到 README.md 中 104 | 105 | 4. 效果预览 106 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/wcejj.jpg) 107 | 108 | 109 | 110 | ## 3 参考 111 | * https://www.jianshu.com/p/302abe331dcb 112 | * https://github.com/ekalinin/github-markdown-toc 113 | 114 | 115 | ## 4 缺点 116 | 117 | * 有少量错误,不准确 118 | * 不能自动更新 119 | ---------- 120 | 121 | 122 | # 5 GitHub-markdown 添加 latex 公式 123 | 124 | * 可以在codecogs先编辑好公式,然后右击公式,选择图象属性,复制其中“源文件”一栏中的url,在markdown文档中以图片格式发布。 125 | 126 | * 可以在Chrome中安装GitHub-latex增强插件----[GitHub with mathjax](https://chrome.google.com/webstore/detail/github-with-mathjax/ioemnmodlmafdkllaclgeombjnmnbima) 127 | 128 | * 公式中不含有空格时,可通过''来发布公式,将连接中的\alpha_A+\beta替换为想输入的公式即可。 129 | 130 | ## 参考 131 | * [蔡浩老师-计算物理课程](https://www.evernote.com/shard/s140/sh/e24ec31a-f5a4-4b89-a040-7dd5f6038850/09e367128b7edc54a16d78f9b943c421) 132 | 133 | -------- 134 | -------------------------------------------------------------------------------- /Techs/Jupyter Notebook 使用技巧.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Jupyter Notebook 使用高效小技巧 3 | tags: 4 | - Tech 5 | categories: 6 | - Tech 7 | toc: true 8 | 9 | --- 10 | 11 | 12 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/dizsp.jpg) 13 | 14 | 15 | --- 16 | ## 0. 安装 笔记本扩展 nbextention 17 | 18 | 19 | ```python 20 | conda install -c conda-forge jupyter_nbextensions_configurator 21 | 22 | # 或者 23 | pip install jupyter_contrib_nbextensions && jupyter contrib nbextension install --user 24 | 25 | ``` 26 | 27 | 安装之后,可以在里面选取你需要的快捷增强--- ☑️勾选之后 自动加入。 28 | 29 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/lfzqn.jpg) 30 | 31 | 32 | 常用的几个: 33 | 34 | Variable Inspector --- 显示变量的值,类型,大小的 35 | 36 | code prettify --- 一键优化代码结构,看起来美观标准不少 37 | 38 | Tabel of contents -- 显示文章目录的 39 | 40 | Toggle all line numbers --- 显示行号: 便于报错检查 41 | 42 | Snippets --- 快速导入经常使用的 库 43 | 44 | > 注意修改 snippets.json. 文件的时候, 不要按照文档给的路径,先自行查找一下 **jupyter --paths** 45 | 看 jupyter 使用的哪个路径, 再去路径下查找 snippets.json文件进行修改。 46 | 47 | ![](http://localhost:8888/nbextensions/snippets/snippets-demo.gif) 48 | 49 | 50 | 51 | **详细可以在主页下面有介绍** 52 | 53 | 54 | ----- 55 | 56 | ## 1. jupyter-notebook 写可以执行代码的幻灯片 57 | 58 | ### rise增强 59 | RISE: "Live" Reveal.js Jupyter/IPython Slideshow Extension---[github](https://github.com/damianavila/RISE) 60 | 61 | **效果预览** 62 | 63 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/c02qi.gif) 64 | 65 | 66 | 67 | ### 安装--base-root 下安装 68 | 69 | ```python 70 | $ conda install -c conda-forge rise 71 | ``` 72 | 73 | * 如果报错 74 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/cvm3x.jpg) 75 | 76 | ```python 77 | $ sudo conda install -c conda-forge rise 78 | 79 | ``` 80 | 81 | * 其他安装---[github](https://github.com/damianavila/RISE) 82 | 83 | 84 | ### 使用 85 | 86 | 1. 添加 slide 87 | 88 | 89 | 2. 预览幻灯片 90 | 91 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/fjdv9.jpg) 92 | 93 | 94 | * 基本操作视频---https://youtu.be/sXyFa_r1nxA 95 | 96 | ### 问题 97 | * 无论在哪个环境下安装,只能在anaconda 的 base-root 环境下打开 jupyter 才有用 98 | 99 | 100 | ------ 101 | 102 | ## 2. jupyter notebook 转换为 github 的 README 文件 103 | 104 | 105 | 106 | ### Let's convert this notebook to a README for the GitHub project's title page: 107 | 108 | ```python 109 | !jupyter nbconvert --to markdown seq2seq.ipynb 110 | !mv seq2seq.md README.md 111 | ``` 112 | 113 | 114 | 或者直接: 115 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/rtyfj.jpg) 116 | 117 | 二者效果稍有不同 118 | 119 | --- 120 | 121 | ## 3. 打开 .ipynb 文件 122 | 123 | 有时候在 GitHub中 打开 .ipynb 文件会 打不开 124 | 125 | 可以将文件链接 复制到 [jupyter viewer](https://nbviewer.jupyter.org/) 126 | 127 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/idgwd.jpg) 128 | 129 | 130 | ---- 131 | 132 | 133 | ## 4. jupyter notebook 嵌入链接 134 | 135 | ```python 136 | 137 | from IPython.display import IFrame 138 | IFrame('https://en.wikipedia.org/wiki/HTTPS', width=800, height=450) 139 | ``` 140 | 141 | 效果 142 | 143 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/yu8m5.jpg) 144 | 145 | ---- 146 | 147 | ## 5. jupyter notebook 嵌入 PDF 148 | 149 | ```python 150 | from IPython.display import IFrame 151 | IFrame('https://arxiv.org/pdf/1406.2661.pdf', width=800, height=450) 152 | ``` 153 | 154 | 效果 155 | 156 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/8mies.jpg) 157 | 158 | ---- 159 | 160 | ## 6. jupyter notebook 不小心删除之后的 恢复 161 | 162 | 不小心删除一段代码 找回的方法 163 | 164 | ```python 165 | for line in locals()['In']: 166 | print(line) 167 | ``` 168 | 169 | --- 170 | 171 | 172 | # 参考: 173 | 174 | 1. https://towardsdatascience.com/bringing-the-best-out-of-jupyter-notebooks-for-data-science-f0871519ca29 175 | 176 | 2. https://mp.weixin.qq.com/s/S_YUXFemUkcuBsXJj6EbSA 177 | 178 | 3. https://github.com/ipython-contrib/jupyter_contrib_nbextensions/issues/1279 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /Techs/Mac app 使用推荐.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mac app使用推荐 3 | tags: 4 | - Tech 5 | - Mac 6 | categories: 7 | - Tech 8 | toc: true 9 | 10 | --- 11 | 12 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/j7jrs.jpg) 13 | 14 | 15 | 16 | > [好用的 app 就像好看的女郎,惊艳!]() 17 | 18 | ----- 19 | ----- 20 | 21 | 22 | APP | 评分| 功能 | 附注 23 | ---| :---: | :---: | :---: 24 | 0.Alfred | 🌟🌟🌟🌟🌟 | 快捷操作 workflow | 神兵利器 25 | 1.Dash | 🌟🌟🌟🌟 | 查找所有 语言的 官方文档 | 不太熟练 26 | 2.Evernote |🌟🌟🌟🌟 | 剪切收藏网页 | 爱不释手 27 | 3.CheatSheet 🆓 | 🌟🌟🌟🌟 | 一键显示所有快捷键 | 😎 28 | 4.Teamviewer | 🌟🌟🌟 | 电脑远程控制,文件互传 |登陆麻烦 29 | 5.Sublime 🆓 | 🌟🌟🌟🌟 | 写代码| 颜值至上 😍 高度自定义 30 | 6.Grammarly | 🌟🌟🌟🌟 | 英文写作 自动检查优化语法,检查拼写错误 | 还不错 31 | 7.Xmind | 🌟🌟 | 绘制脑图 | 百度脑图🆓做的更好看些,Mindnode💰更加好看便捷。 32 | 8.Mendelay 🆓 | 🌟🌟🌟 | 文献整理阅读 | 配合 Chrome(或其他浏览器)的插件使用,便于收集整理论文。 33 | 9.Sharemouse 🆓 | 🌟🌟 | 电脑间屏幕 无线共享|响应不是很灵敏 34 | 10.Airserve 🆓 | 🌟🌟🌟🌟| 手机投屏| 很有趣 ,很便捷 35 | 11.Ipaste 🆓 | 🌟🌟🌟 | 记住剪切历史| 国产,使用的有些问题 替换 Paste 💰 36 | 12.Itcycle 🆓 | 🌟🌟 | 日历标记日程| 可以随时添加提醒事项, 就是颜值太一般 😌 37 | 13.Bartender 🆓 | 🌟🌟🌟 | 隐藏 Mac 上方不常用icon | 不能调整顺序 38 | 14.Agenda | 🌟🌟🌟🌟| 日程编辑记录 | 颜值很高,很便捷😍 39 | 15.Qbserve 💰 | 🌟🌟🌟🌟 | 记录Mac使用各种项目上的时间 | 不太准确 ,耗电,付费 40 | 16.Surge | | 超强网络管理 | 41 | 17-1.GitHub Desktop | 🌟🌟🌟🌟| 方便更改文件,文件位置 | 一些问题不太方便 42 | 17-2.OhMyStar |🌟🌟🌟🌟| 清晰快捷管理自己 star| 页面内不方便打开项目 43 | 17-3.GitKraken | 🌟🌟🌟| 图形化 Git 操作 | 不太熟练 44 | 17-4.Gitup | 🌟🌟🌟 | git 托管 代码 | 方便 简洁 45 | 18.Go2shell | 🌟🌟🌟 | 快速打开文件路径终端| 准确简捷 46 | 19.Caffeine | 🌟🌟🌟 | 定时休眠 | 记笔记,下文件避免休眠 47 | 20.VideoProc| 🌟🌟🌟 | 下载剪辑视频 | 下载YouTube ,相应速度有一些慢 48 | 21.IINA | 🌟🌟🌟 | 轻量视频播放器 | 打开网页播放的 URl-- 一些打不开 49 | 22.ipic| 🌟🌟🌟🌟 | 快速图床 | 快速生成图片的markdown 链接 50 | 23.Tiny4png| 🌟🌟🌟 | 压缩图片 | 快速压缩图片大小 51 | 24.Gif brewery3 | 🌟🌟🌟🌟 | 转换GIF | 视频 图片转换为 GIF 52 | 25.Tweeten | 🌟🌟🌟 | twitter mac端 | 界面丑,不好操作,自定义少 53 | 26.Spectale | 🌟🌟🌟🌟 | 快速分屏 | 操作简单,分屏效果略差 54 | 27.Feeds| 🌟🌟🌟 | 轻量的 RSS 订阅 | 阅读不方便, 55 | 28.Reeder3 | 🌟🌟🌟🌟 | RSS 订阅 | 方便 56 | 29.import.io | | 快速爬虫 | 57 | 30.cdock | | 自定义 dock 栏 | 58 | 31.notion | | | 59 | 60 | 61 | ----- 62 | 63 | # 后续会补充一些 app 具体的使用踩坑或者 tips 64 | 65 | 66 | -------------------------------------------------------------------------------- /Techs/mac iterm2 配置.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mac OS 中的 iterm2 安装配置 3 | tags: 4 | - Mac 5 | categories: 6 | - Tech 7 | toc: true 8 | mathjax: true 9 | --- 10 | ![](https://github.com/LiuChuang0059/large_file/blob/master/pic/tjupg.jpg) 11 | --- 12 | 13 | ## 1. iterm2 安装(需要安装homebrew) 14 | ``` 15 | brew cask install iterm2 16 | ``` 17 | 18 | ## 2. oh-my-zsh 安装(在下载的iterm2 中输入代码)![屏幕快照 2018-07-31 下午5.33.48.png-90.1kB][1] 19 | ``` 20 | curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh 21 | ``` 22 | 23 | ## 3. 安装 [powerline](https://github.com/powerline/fonts)(需要安装pip) 24 | ``` 25 | pip install powerline-status 26 | ``` 27 | ## 4. 安装字体库 28 | ``` 29 | git clone https://github.com/powerline/fonts.git 30 | cd fonts 31 | ./install.sh 32 | ``` 33 | ![屏幕快照 2018-07-31 下午6.07.41.png-57.8kB][2] 34 | 35 | 36 | ## 5. 设置iTerm 2的Regular Font 和 Non-ASCII Font 37 | ![屏幕快照 2018-07-31 下午6.25.11.png-466.5kB][3] 38 | 39 | ## 6 设置配色方案 40 | github 下载 41 | ``` 42 | git clone https://github.com/altercation/solarized 43 | ``` 44 | 进入刚刚下载的工程的solarized/iterm2-colors-solarized 下双击 Solarized Dark.itermcolors 和 Solarized Light.itermcolors 两个文件就可以把配置文件导入到 iTerm2 里 45 | 46 | 47 | ![屏幕快照 2018-07-31 下午6.58.21.png-435.9kB][4] 48 | 49 | ## 7 使用[agnoster](https://github.com/fcamblor/oh-my-zsh-agnoster-fcamblor)主题 50 | ``` 51 | git clone https://github.com/fcamblor/oh-my-zsh-agnoster-fcamblor 52 | cd oh-my-zsh-agnoster-fcamblor 53 | ./install 54 | ``` 55 | 进入~/.zshrc打开.zshrc文件,然后将ZSH_THEME后面的字段改为agnoster。ZSH_THEME="agnoster"(agnoster即为要设置的主题) 56 | 57 | ## 8增加指令高亮效果——zsh-syntax-highlighting 58 | 59 | ``` 60 | git clone git://github.com/zsh-users/zsh-syntax-highlighting.git 61 | 62 | ``` 63 | 64 | 1)cd到.zshrc所在目录 65 | 66 | 2)执行指令将工程克隆到当前目录 67 | 68 | git clone git://github.com/zsh-users/zsh-syntax-highlighting.git 69 | 70 | 3)打开.zshrc文件,在最后添加下面内容 71 | 72 | source XXX/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 73 | 74 | 保存文件。 75 | 76 | 注意:xxx代表.zshrc所在目录 77 | 78 | 4)cd ~/.oh-my-zsh/custom/plugins 79 | 80 | 5)再次打开.zshrc文件,在最后面添加下面内容 81 | 82 | plugins=(zsh-syntax-highlighting) 83 | 84 | 保存文件。 85 | ## 9 添加自动补全 类同 86 | ``` 87 | cd ~/.oh-my-zsh/custom/plugins/ 88 | git clone https://github.com/zsh-users/zsh-autosuggestions 89 | vi ~/.zshrc 90 | ``` 91 | 92 | 找到plugins,加上这个插件即可: 93 | 94 | 95 | # 参考 96 | https://www.jianshu.com/p/7de00c73a2bb 97 | http://matt33.com/2016/07/09/mac-software/ 98 | https://github.com/sirius1024/iterm2-with-oh-my-zsh 99 | 100 | [1]: http://static.zybuluo.com/zzzxxxyyy/ntps6d27969t8eg4pbxd3bpo/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202018-07-31%20%E4%B8%8B%E5%8D%885.33.48.png 101 | [2]: http://static.zybuluo.com/zzzxxxyyy/8xfbidgbn5yjba4ii5vot3qn/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202018-07-31%20%E4%B8%8B%E5%8D%886.07.41.png 102 | [3]: http://static.zybuluo.com/zzzxxxyyy/lyzvtg5ovdohm3c6k1nj6agh/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202018-07-31%20%E4%B8%8B%E5%8D%886.25.11.png 103 | [4]: http://static.zybuluo.com/zzzxxxyyy/ihrbyhg59z7nnylgs0f7hp3x/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202018-07-31%20%E4%B8%8B%E5%8D%886.58.21.png --------------------------------------------------------------------------------