《吴恩达 - 机器学习》笔记

学习资源


b站:机器学习(Machine Learning)- 吴恩达(Andrew Ng)
网易:吴恩达《机器学习》
网易的版本更好一点,至少字幕不会遮挡视频内容。

文字整理版:吴恩达《机器学习》文字整理版

这个是别人的学习笔记视频:吴恩达深度学习课程(全):第一遍学习完结

章节1 绪论:初识机器学习


课时1 欢迎参加《机器学习》课程

开篇blablabla,可以跳过不看。

课时2 什么是机器学习?

什么是机器学习?由Tom Mitchell提出,来自卡内基梅隆大学,Tom定义的机器学习是,一个好的学习问题定义如下,他说,一个程序被认为能从经验E中学习,解决任务T,达到性能度量值P,当且仅当有了经验E后,经过P评判,程序在处理T时的性能有所提升。

课时3 监督学习

监督学习指的就是我们给学习算法一个数据集。这个数据集由“正确答案”组成。
回归问题:我们在试着推测出这一系列连续值属性,比如房子的价格。
分类问题:我们试着推测出离散的输出值:0或1,而事实上在分类问题中,输出可能不止两个值。
我们以后会讲一个算法,叫支持向量机,里面有一个巧妙的数学技巧,能让计算机处理无限多个特征。

监督学习其基本思想是,我们数据集中的每个样本都有相应的“正确答案”。再根据这些样本作出预测,就像房子和肿瘤的例子中做的那样。我们还介绍了回归问题,即通过回归来推出一个连续的输出,之后我们介绍了分类问题,其目标是推出一组离散的结果。

一直对于“回归问题”这个词有疑惑,为什么叫“回归”?搜索了一下,“回归”的来源如下:
“回归”这一词最初是用来形容“向平均回归”的现象。
生物统计学家高尔顿研究父母身高和子女身高时发现“即使父母的身高都‘极端’高,其子女不见得会比父母高,而是有“衰退”(regression)(也称作“回归)至平均身高的倾向”具体说明一下:高尔顿当时拟合了父母平均身高 x 和 子女平均身高 y 的经验方程:y = 3.78+0.516x。可以看到,父代身高每增加一个单位, 其成年子女的平均身高只增加0.516个单位, 它反映了这种“衰退”效应(“回归”到正常人平均身高)虽然之后的x 与 y 变量之间并不总是具有“衰退”(回归)关系,但是为了纪念高尔顿这位伟大的统计学家,“线性回归”这一名称就保留了下来。

回归,regression,最初是指人的身高的回归,也就是说,个子高的父母倾向于生相对矮的孩子,个子矮的父母倾向于生个子相对高的孩子,从而使得后代的身高朝向某一个中间水平回归。后来,回归被理解为一种统计方法,用来研究一些自变量如何影响因变量
高尔顿用这种方法,发现了他称之为“向平均回归”(regression to the mean)的现象,这表现为:非常高的父亲,其儿子往往要比父亲矮一些;而非常矮的父亲,其儿子往往要比父亲高一些。似乎是某种神秘的力量,使得人类的身高从高矮两极移向所有人的平均值。不只是人类身高存在着向平均数回归的现象,几乎所有的科学观察都着了魔似的向平均值回归。在第5章到第7章,我们将看到,费歇尔如何能够将高尔顿向平均值回归的思想纳入统计模型,而这种模型现在支配着经济学、医学研究和工程学的很多内容。

高尔顿仔细思考了他的惊人发现,而后认识到这必定是真实的,在进行所有观察之前这就是可以预言的。他说,假设不发生这种向平均值的回归,那么从平均意义上看,高身材父亲的儿子将与他们的父亲一样高,在这种情况下,一些儿子的身材必须高于他们的父亲,以抵消身材比父亲矮小者的影响,使平均值不变。高身材者这一代人的儿子也将如此,那么会有一些儿子身材更高。这个过程将一代一代延续下去。同样地,将会有一部分儿子身材比他们的父亲矮小,而且有一部分孙子将更加矮小,如此下去,不用多少代,人类种族就将由特别高和特别矮的两极构成。 上述的情形并没有发生,人类的身高在平均意义上趋向于保持稳定。只有当非常高的父亲其儿子平均身材变矮,而非常矮的父亲其儿子的平均身材变高,才能出现这种稳定。向平均值回归是一种保持稳定性的现象,它使得某给定物种代际之间大致相同。

课时4 无监督学习

无监督学习,它是学习策略,交给算法大量的数据,并让算法为我们从数据中找出某种结构。
在无监督学习中,我们已知的数据。看上去有点不一样,不同于监督学习的数据的样子,即无监督学习中没有任何的标签或者是有相同的标签或者就是没标签。所以我们已知数据集,却不知如何处理,也未告知每个数据点是什么。别的都不知道,就是一个数据集。你能从数据中找到某种结构吗?针对数据集,无监督学习就能判断出数据有两个不同的聚集簇。这是一个,那是另一个,二者不同。是的,无监督学习算法可能会把这些数据分成两个不同的簇。所以叫做聚类算法。
聚类只是无监督学习中的一种。

课时5 问题

一些问题,英文的,我没看。

章节2 单变量线性回归


课时6 模型描述

学到一个单词:hypothesis

| hypothesis |
| 英[haɪˈpɒθəsɪs]| 美[haɪˈpɑːθəsɪs]|
意思是"假设"。

h\theta(x)缩写为h(x)即是李宏毅讲的f(x),假设有一个Function的意思吧。
线程回归模型(Linear Regression):

h(x)=\theta_{0}+\theta_{1}x

因为只含有一个特征/输入变量,因此这样的问题叫作单变量线性回归问题。

课时7 代价函数

h(x)=\theta_{0}+\theta_{1}x

这里的\theta_{0}\theta_{1}代表参数。
公式类似李宏毅所讲的:f(x)=w\cdot x+b\theta_{0}相当于b\theta_{1}相当于w

Cost Function代价函数,平方误差代价函数(square error function):

J(\theta_{0},\theta_{1})=\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}
m代表训练样本数目。
y代表正确数值。

目标是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得代价函数最小。

代价函数也被称作平方误差函数,有时也被称为平方误差代价函数。我们之所以要求出误差的平方和,是因为误差平方代价函数,对于大多数问题,特别是回归问题,都是一个合理的选择。还有其他的代价函数也能很好地发挥作用,但是平方误差代价函数可能是解决回归问题最常用的手段了。

课时8 代价函数(一)

Hypothesis(假设即Function):
h(x)=\theta_{0}+\theta_{1}x

Cost Function(代价函数):
J(\theta_{0},\theta_{1})=\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}

Goal(目标):
\underset{\theta_0,\theta_1}{minimize}\ J(\theta_0,\theta_1)
即:目标是为了让代价函数最小。

现在假设\theta_0=0,然后\theta_1取不同的值画出函数,其结果是一个U型的函数,就这是代价函数的样子。

课时9 代价函数(二)

代价函数的样子,等高线图,则可以看出在三维空间中存在一个使得J(\theta_0,\theta_1)最小的点。
我们真正需要的是一种有效的算法,能够自动地找出这些使代价函数J取最小值的参数\theta_0\theta_0来。

课时10 梯度下降

梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数J(\theta_0,\theta_1)的最小值。
选择不同的初始参数组合,可能会找到不同的局部最小值。

公式:

repeat until convergence {
\theta_{j} := \theta_{j} - \alpha \frac{\partial }{\partial \theta_{j}}J(\theta_{0},\theta_{1}) (for j=0 and j=1)
}
Correct: Simultaneous update
temp0:=\theta_{0} - \alpha \frac{\partial }{\partial \theta_{0}}J(\theta_{0},\theta_{1})
temp1:=\theta_{1} - \alpha \frac{\partial }{\partial \theta_{1}}J(\theta_{0},\theta_{1})
\theta_{0} := temp0
\theta_{1} := temp1

解析:
:=:赋值符号。
\alpha:learning rate,学习率。
\frac{\partial }{\partial \theta_{j}}J(\theta_{0},\theta_{1}) :这是一个导数项,暂时不解析原理。
Correct: Simultaneous update的意思是同时把\theta_{0},\theta_{1}代入公式后计算出的值再赋值给\theta_{0},\theta_{1},也就是用一对参数同时经过公式计算后的结果再更新参数,即同步更新参数。

梯度下降要同时更新\theta_{0},\theta_{1}

课时11 梯度下降知识点总结

导数是变化率、是切线的斜率、是速度、是加速度。

求导的目的: 基本上可以说取这个红点的切线,就是这样一条红色的直线,刚好与函数相切于这一点,让我们看看这条红色直线的斜率,就是这条刚好与函数曲线相切的这条直线,这条直线的斜率正好是这个三角形的高度除以这个水平长度,现在,这条线有一个正斜率,也就是说它有正导数,因此,我得到的新的\theta_{1}\theta_{1}更新后等于\theta_{1}减去一个正数乘以\alpha
这就是梯度下降法的更新规则:
\theta_{j} := \theta_{j} - \alpha \frac{\partial }{\partial \theta_{j}}J(\theta)

随着梯度下降法的运行,你移动的幅度会自动变得越来越小,直到最终移动幅度非常小,你会发现,已经收敛到局部极小值。

梯度下降算法,你可以用它来最小化任何代价函数J,不只是线性回归中的代价函数J

我的理解:
我们的目的是让代价函数J(\theta) 最小,而代价函数的大小是由多个参数\theta决定的,所以我们是要求出合适的\theta参数。
一开始先随机取\theta,然后用梯度下降不断更新\theta,学习率就是更新的步伐,每次移动一点,当找到局部最优点时导数为0,此时\theta停止更新(减零等于没有更新)。所以梯度下降可以让我们找到局部最优点(局部最低点)。

课时12 线性回归的梯度下降

把上面梯度下降和代价函数公式和Hypothesis Function合并整理一下得到:

\alpha \frac{\partial }{\partial \theta_{j}}J(\theta_{0},\theta_{1}) = \alpha \frac{\partial }{\partial \theta_{j}}\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}
= \alpha \frac{\partial }{\partial \theta_{j}}\frac{1}{2m}\sum_{i=1}^{m}(\theta_{0}+\theta_{1}x^{(i)}-y^{(i)})^{2}

这个公式先不管怎么推导出来:

repeat until convergence {
\theta_{0} := \theta_{0} - \alpha \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})
\theta_{1} := \theta_{1} - \alpha \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})\cdot x^{(i)}
}

我:如果学过微积分上述公式可以很简单的推导出来,其实就是对\theta_{0}\theta_{1}分别求导。

这种方法叫批量梯度下降。

高等线性代数中的正规方程(normal equations)方法也可以代价函数的最小值。实际上在数据量较大的情况下,梯度下降法比正规方程要更适用一些。

课时13 本章课程总结

每节课的ppt。

章节 3 线性代数回顾


课时14 矩阵和向量

矩阵写法:行\ast 列
矩阵元素:A_{ij}表示A矩阵的i行j列的元素,i, j的索引一般从1开始,当然也可以从0开始,但是本课程约定从1开始。
向量:一种特殊的矩阵:n\ast 1矩阵,一般也称之为n维向量。
一般惯例以大写字母表示矩阵或者向量,小写字母表示下标。

课时15 加法和标量乘法

矩阵加法:矩阵维数要相同,将对应索引的元素直接相加得到新的矩阵。
scalar标量:代表一个实数。
标量跟矩阵相乘:将标量与矩阵元素逐个相乘即可。该乘法符合交换率。除法一样,因为除法也可以写成乘法的倒数。

课时16 矩阵向量乘法

矩阵与向量相乘:矩阵m\ast n 与向量n相乘,结果是m\ast 1的矩阵,也就是向量m
乘法过程:
取矩阵第1行的每一列与向量对应的行相乘并将结果相加,得到结果向量的第1行。矩阵逐行做此操作得到最终的结果。

课时17 矩阵乘法

矩阵与矩阵相乘:矩阵m\ast n 只能与n\ast o的矩阵相乘,也就是说左边的列要等于右边的行,结果是m\ast o的矩阵,矩阵乘法不符合交换率。
乘法过程:
先拿右边矩阵的第一列做为向量跟左边的矩阵做向量与矩阵乘法,结果是一列向量,然后再拿右边第2列与左边矩阵做乘法......

课时18 矩阵乘法特征

矩阵乘法不符合交换率,就算是行和列的维度都相同也不行,比如A(m\ast m) \times B(m\ast m) \neq B(m\ast m) \times A(m\ast m)
矩阵乘法符合结合率:(A \times B) \times C = A \times (B \times C)
单位矩阵:I_{n\times n},左上角到右下角的对角线的值都为1,其余元素值为0。
对于所有的矩阵A都有:

A\cdot I = I \cdot A = A

课时19 逆和转置

\color{red}{逆:}

如果A是一个m\times m的矩阵,而且A有其逆矩阵也就是说不是所有矩阵都有逆矩阵,则:

AA^{-1}=A^{-1}A=I
其中:A^{-1}是逆矩阵,I是单位矩阵。

只有m\times m的对称矩阵(又叫方阵)才有逆矩阵。

虽然课程里使用Octave做为编程工具,但是听说吴恩达改为python,而且python确实更实用,所以我这儿也用python+numpy做书中的例子。

python numpy求逆矩阵:

m1 = np.matrix([[3,4],[2,16]]) 
m2 = np.linalg.inv(m1)
print(m2)
print(m1*m2)

结果:

[[ 0.4   -0.1  ]
 [-0.05   0.075]]
[[1. 0.]
 [0. 1.]]

没有逆矩阵的矩阵称之为:singular奇异矩阵或者dengenerate退化矩阵**。

\color{red}{转置:}
A的转置写为:A^T
操作:将A的第1行写做A^T的第1列,第2行写做第2列......
一句话:行转列。

A^T_{ij} = A_{ji}

章节4 配置


MTLAB和Octave的课程。
我不用这两个软件,直接跳过该课程。

章节5 多变量线性回归


课时28 多功能

这个课名翻译为多功能有问题,原英文为Multiple Features,应该翻译为多维特征。

h_{\theta}(x)=\theta^TX=\theta_{0}x_{0}+\theta_{1}x_{1}+\theta_{2}x_{2}+...+\theta_{n}x_{n}

n代表特征的数量。
x代表特征,x^{(i)}代表第i个训练实例,是特征矩阵中的第i行,是一个向量(vector)。
上面的x_0值固定为1,是我们为了下面的矩阵运算而添加上去的。
x_{j}^{(i)}代表特征矩阵中第i行的第j个特征,也就是第i个训练实例的第j个特征。
\theta^TX中的\theta是列向量\begin{bmatrix} \theta_0\\ \theta_1\\ ...\\\theta_n\end{bmatrix}X\begin{bmatrix} x_0\\ x_1\\ ...\\x_n\end{bmatrix}
\theta^T转置后为:\begin{bmatrix}\theta_0 &\theta_1 &... &\theta_n \end{bmatrix},然后与列向量X相乘,自然就是\theta_{0}x_{0}+\theta_{1}x_{1}+\theta_{2}x_{2}+...+\theta_{n}x_{n}

课时29 多元梯度下降法

构建一个代价函数,则这个代价函数是所有建模误差的平方和,即:
J(\theta_0,\theta_1,...,\theta_n)=\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}
其中h_{\theta}(x)=\theta^TX=\theta_{0}x_{0}+\theta_{1}x_{1}+\theta_{2}x_{2}+...+\theta_{n}x_{n}
找出使得代价函数最小的一系列参数, 多变量线性回归的批量梯度下降算法为:
Repeat \{ \\ \theta_{j} := \theta_{j} - \alpha \frac{\partial }{\partial \theta_{j}}J(\theta_0,\theta_1,...,\theta_n) \\ \}
即:
Repeat \{ \\ \theta_{j} := \theta_{j} - \alpha \frac{\partial }{\partial \theta_{j}}\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2} \\ \}
求导数后得到:
Repeat \{ \\ \theta_{j} := \theta_{j} - \alpha \frac{1}{m}\sum_{i=1}^{m}((h_\theta(x^{(i)})-y^{(i)})\cdot x_{j}^{(i)}) \\ (同步更新\theta_{j},for \ j = 0, 1,...n) \\ \}
例:当n>=1时:
\theta_{0} := \theta_{0} - \alpha \frac{1}{m}\sum_{i=1}^{m}((h_\theta(x^{(i)})-y^{(i)})\cdot x_{0}^{(i)})
\theta_{1} := \theta_{1} - \alpha \frac{1}{m}\sum_{i=1}^{m}((h_\theta(x^{(i)})-y^{(i)})\cdot x_{1}^{(i)})
\theta_{2} := \theta_{2} - \alpha \frac{1}{m}\sum_{i=1}^{m}((h_\theta(x^{(i)})-y^{(i)})\cdot x_{2}^{(i)})

代价函数代码示例:

def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)
    return np.sum(inner) / (2 * len(X))
课时30 多元梯度下降法演练I - 特征缩放

特征缩放可以使梯度下降运行的更快。
根据经验,特征值范围在:-3\leqslant x\leqslant 3或者-\frac{1}{3}\leqslant x\leqslant \frac{1}{3}之间比较合适。

最简单的方法是令:x_n=\frac{x_n-\mu_n}{s_n},其中\mu_n 是平均值,s_n是标准差,即最大值减去最小值。

课时31 多元梯度下降法II – 学习率

学习率太小可能运行的太慢,学习率太大时可能不会在每次迭代时都下降,甚至可能不收敛。
绘制J(\theta)随迭代步数变化的曲线可以帮助弄清楚情况。
经验:学习率\alpha的取值:
...,0.001,0.003,0.01,0.03,0.1,0.3,1...,也就是按3的倍数取值。

课时32 特征和多项式回归

线性回归并不适用于所有数据,有时我们需要曲线来适应我们的数据,比如一个二次方模型: h_\theta=\theta_0+\theta_1x_1+\theta_2 x_2^2或者三次方模型: h_\theta=\theta_0+\theta_1x_1+\theta_2 x_2^2+\theta_3 x_3^3
通常我们需要先观察数据然后再决定准备尝试怎样的模型。 另外,我们可以令:
x_2= x_2^2x_3= x_3^3,从而将模型转化为线性回归模型。

如果我们采用多项式回归模型,在运行梯度下降算法前,特征缩放非常有必要。

课时33 正规方程(区别于迭代方法的直接解法)

正规方程法(Normal Equation)求最优\theta公式,视频中未推导此公式只给出结果:

\theta=(X^{T}X)^{-1}X^{T}y
上标^T代表矩阵转置,上标^{-1}代表矩阵的逆。

python实现:

theta = (np.linalg.inv(x.T*x))*x.T*y

正规方程法不需要特征缩放。

梯度下降法缺点:

  1. 需要选择合适的学习率。
  2. 需要多次迭代,速度更慢。

正规方程优点:

  1. 需要选择学习率。
  2. 不需要多次迭代。

梯度下降法优点:

  1. 特征变量很多的时候也可以工作的很好。
  2. 适用于各种类型的模型。

正规方程缺点:

  1. 求逆矩阵的代价以矩阵维度的3次方增长,所以如果矩阵维度n很大也就是有很多特征变量的时候,那么计算速度是很慢的。
    当n小于1000时还是足够快,当大于10000时已经开始有点慢了已经可以考虑梯度下降法,当n更大的时候当然选择梯度下降。
  2. 只适用于线性模型,不适合逻辑回归模型等其他模型。
import numpy as np
 def normalEqn(X, y):
   theta = np.linalg.inv(X.T@X)@X.T@y #X.T@X等价于X.T.dot(X)
   return theta
课时34 正规方程在矩阵不可逆情况下的解决方法

这节课选学。
出现不可逆的情况还是比较少的,在python中可以使用pinv函数,这样当不可逆时算法也不会出错。
python:
np.linalg.pinv可以求伪逆矩阵。
np.linalg.inv只能求逆矩阵。

课时35 导师的编程小技巧

Octave提交作业相关。跳过。

课时36 本章课程总结

章节ppt。

课时37 课件资料下载方法

跳过。

章节6 Octave/Matlab 教程


跳过。

章节7 Logistic 回归


逻辑回归为什么叫逻辑回归?是因为使用了sigmoid函数,sigmoid函数本身也是Logistic function的一种形式,故此得名。逻辑回归是一种广义的线性回归分析模型,Sigmoid函数是逻辑回归的核心,通过Sigmoid函数将原本的线性回归问题转化成了一个分类问题。
Logistic回归是用来解决二类分类问题的,如果要解决的问题是多分类问题呢?那就要用到softmax回归了,它是Logistic回归在多分类问题上的推广。此处神经网络模型开始乱入,softmax回归一般用于神经网络的输出层,此时输出层叫做softmax层。

课时 46 分类

y\in \{0,1\}
0: Nagative Class 负类
1: Positive Class 正类

Logistic Regression(逻辑回归)是一种分类算法。这个算法的性质是:它的输出值永远在0到 1 之间。

课时47 假设陈述

Logistic Regression Model:
想要最终的输出结果界于0-1之间:0\leqslant h_{\theta}(x)\leqslant 1

h_{\theta}(x)=g(\theta^TX)

x代表特征向量,g代表逻辑函数。
Sigmoid function和Logistic function这两个术语一个意思,公式:

g(z)=\frac{1}{1+e^{-z}}

把上式公式合并一下:

h_{\theta}(x)=\frac{1}{1+e^{-\theta^TX}}

Sigmoid函数从接近0慢慢经过0.5直至趋近于1。
g(z)中的z趋于无穷大时g(z)接近1,当z趋于无穷小时g(z)接近0,当z等于0时g(z)为0.5。
所以h_{\theta}(x)的最终结果界于0-1之间。

课时48 决策界限

所谓决策边界就是把某个值比如0.5当作边界来区分出0和1。
我们可以用非常复杂的模型来适应非常复杂形状的判定边界。

课时49 代价函数

从线性回归公式转过来:

J(\theta_{0},\theta_{1})=\frac{1}{m}\sum_{i=1}^{m}(Cost(h_{\theta}(x^{(i)}), y^{(i)}))
Cost(h_{\theta}(x^{(i)}), y^{(i)})=\frac{1}{2}(h\theta(x^{(i)})-y^{(i)})^{2}

简化去掉上标变为:

Cost(h_{\theta}(x), y)=\frac{1}{2}(h\theta(x)-y)^{2}

但使用Sigmoid函代入后这是一个非凸函数,在梯度下降时无法找到全局最小值。
所以我们需要一个新的代价函数。

\left\{\begin{matrix} -log(h_{\theta}(x))) & if\ y=1\\ -log(1-h_{\theta}(x))) & if\ y=0 \end{matrix}\right.
Note: y=0 or 1 always

下一节课给出代价函数。

课时50 简化代价函数与梯度下降

将上一节课的公式整理合并,从统计学极大似然法得到:

J(\theta)=\frac{1}{m}\sum_{i=1}^{m}Cost(h_{\theta}(x^{(i)}), y^{(i)})
=-\frac{1}{m}[\sum_{i=1}^{m}y^{(i)}logh_{\theta}(x^{(i)})+(1-y^{(i)})log(1-h_{\theta}(x^{(i)}))]

我们的目的是找出让J(\theta)取得最小值的\theta,使用梯度下降法来完成。
公式:

\theta_{j} := \theta_{j} - \alpha\sum_{i=1}^{m}(h\theta(x^{(i)})-y^{(i)})x_{j}^{(i)}

说是跟线性回归的公式一样(但好像有点不同啊)。

线性回归:h_{\theta}x=\theta^Tx
这里的逻辑回归:h_{\theta}(x)=\frac{1}{1+e^{-\theta^Tx}}
使用for循环来更新\theta,也可以使用速度更快的向量化方式同时更新参数。

线性回归中的特征缩放也可以应用到逻辑回归中。

课时51 高级优化

共轭梯度法(Conjugate gradient)、BFGS和L-BFGS。
优点:不需要手动选择学习率。
缺点:比梯度下降法更复杂。
不要自己实现这些算法而是去调用现成的库。
后面讲了个Octave例子,fminunc加强版梯度下降,会自动选择学习率。
我们一般用python,不需要关心这个例子的具体代码。

课时52 多元分类:一对多

我自己总结一下吧(跟原视频内容不一样,意思是一样的):
比如有三个类别,我们现在要分出来,那么分别对3个类别建立3个模型并进行训练。每个模型都可以获得一个类别的概率值结果,测试时分别在三个模型中都输入参数x得到三个结果,此时取最大的那个概率结果就可以分出x的类别。
例:有三种不同水果:桃,苹果,香蕉。
对桃取值为1,其他两类归于0,做模型进行训练。
对苹果取值为1,其他两类归于0,做模型进行训练。
对香蕉取值为1,其他两类归于0,做模型进行训练。
现在我们有了三个模型,可以对一个输入值进行判断分类,分类结果取出最大值的那个就是类别。

课时53 本章课程总结

章节ppt。

课时54 课件资料下载方法

跳过。

章节8 正则化


课时55 过拟合问题

如果我们发现了过拟合问题,应该如何处理?

  1. 丢弃一些不能帮助我们正确预测的特征。可以是手工选择保留哪些特征,或者使用一些模型选择的算法来帮忙(例如PCA)
  2. 正则化。 保留所有的特征,但是减少参数的大小(magnitude)。
课时56 代价函数

为了防止过拟合我们在代价函数中加入惩罚,但是我们并不知道其中哪些特征我们要惩罚,我们将对所有的特征进行惩罚,并且让代价函数最优化的软件来选择这些惩罚的程度。这样的结果是得到了一个较为简单的能防止过拟合问题的假设:

J(\theta)=\frac{1}{2m}[\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^{2}+\lambda \sum_{j=1}^{n}\theta_j^{2}]
其中\lambda又称为正则化参数(Regularization Parameter)。 注:根据惯例,我们不对\theta_0进行惩罚。

我们令\lambda的值很大的话,为了使Cost Function 尽可能的小,所有的\theta的值(不包括\theta_0)都会在一定程度上减小。
对于正则化,我们要取一个合理的 的值,这样才能更好的应用正则化。 回顾一下代价函数,为了使用正则化,让我们把这些概念应用到到线性回归和逻辑回归中去,那么我们就可以让他们避免过度拟合了。

课时57 线性回归的正则化

因为我们未对\theta_0进行正则化,所以梯度下降算法将分两种情形:

Repeat until convergence {
{\theta_0}:={\theta_0}-a\frac{1}{m}\sum\limits_{i=1}^{m}{(({h_\theta}({{x}^{(i)}})-{{y}^{(i)}})x_{0}^{(i)}})
{\theta_j}:={\theta_j}-a[\frac{1}{m}\sum\limits_{i=1}^{m}{(({h_\theta}({{x}^{(i)}})-{{y}^{(i)}})x_{j}^{\left( i \right)}}+\frac{\lambda }{m}{\theta_j}]
for j=1,2,...n
}

整理式子可得:

{\theta_j}:=\theta_j(1-a\frac{\lambda }{m})-a\frac{1}{m}\sum\limits_{i=1}^{m}{({h_\theta}({{x}^{(i)}})-{{y}^{(i)}})x_{j}^{\left( i \right)}}

可以看出,正则化线性回归的梯度下降算法的变化在于,每次都在原有算法更新规则的基础上令\theta值减少了一个额外的值。

我们同样也可以利用正规方程来求解正则化线性回归模型(公式不写了)。

课时58 课件资料下载方法

跳过。

课时59 本章课程总结

跳过。

课时60 编程作业:Logistic 回归

跳过。

课时61 Logistic 回归的正则化

高级优化算法需要自己设计代价函数J(\theta)
我们也给代价函数增加一个正则化的表达式,得到代价函数:

J(\theta)=\frac{1}{m}[\sum_{i=1}^{m}-y^{(i)}logh_{\theta}(x^{(i)})-(1-y^{(i)})log(1-h_{\theta}(x^{(i)}))]+\frac{\lambda }{2m}\sum_{j=1}^{n}\theta_j^{2}

import numpy as np
def costReg(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    first = np.multiply(-y, np.log(sigmoid(X*theta.T)))
    second = np.multiply((1 - y), np.log(1 - sigmoid(X*theta.T)))
    reg = (learningRate / (2 * len(X))* np.sum(np.power(theta[:,1:theta.shape[1]],2))
    return np.sum(first - second) / (len(X)) + reg

代码解析一下:
主要是这一行:

theta[:,1:theta.shape[1]]

Mat[:, m:n]表示取矩阵Mat的所有行中的的第m到n-1列数据,含左m不含右n。
theta.shape[1]表示取矩阵的列数,theta.shape[0]表示取矩阵的行数。
theta[:,1:theta.shape[1]]的意思是取矩阵theta所有行中第1到最后列的数据,即返回的是排除第0列的矩阵,因为\theta_0不参与其中的任何一个正则化。

Repeat until convergence {
{\theta_0}:={\theta_0}-a\frac{1}{m}\sum\limits_{i=1}^{m}{(({h_\theta}({{x}^{(i)}})-{{y}^{(i)}})x_{0}^{(i)}})
{\theta_j}:={\theta_j}-a[\frac{1}{m}\sum\limits_{i=1}^{m}{({h_\theta}({{x}^{(i)}})-{{y}^{(i)}})x_{j}^{\left( i \right)}}+\frac{\lambda }{m}{\theta_j}]
for j=1,2,...n
}

看上去同线性回归一样,但是h_{\theta}(x)=g(\theta^TX),所以与线性回归不同。

  1. 虽然正则化的逻辑回归中的梯度下降和正则化的线性回归中的表达式看起来一样,但由于两者的h_{\theta}(x)不同所以还是有很大差别。
  2. \theta_0不参与其中的任何一个正则化。

章节9 神经网络学习


课时62 非线性假设

对于图片来说我们用这些图片上一个个像素的值(饱和度或亮度)来作为特征。
我们只选用灰度图片,每个像素则只有一个值(而非 RGB值)。
一张50*50的灰度图有2500个像素代表了2500个特征变量,特征变量x就是灰度值。
如果是RGB则是7500个特征变量。
每个通道的颜色值有0-255,所以总的特征是百万级的,这太庞大了,普通的逻辑回归模型,不能有效地处理这么多的特征,这时候我们需要神经网络。

课时63 神经元与大脑

闲话,没必要看。

课时64 模型展示Ⅰ

神经元也叫激活单元,activation unit。
之前视频说的参数\theta,在神经网络里一般称之为weight,也就是权重w

image.png

其中是输入单元(input units),我们将原始数据输入给它们。是中间单元,它们负责将数据进行处理,然后呈递到下一层。 最后是输出单元,它负责计算。

神经网络模型是许多逻辑单元按照不同层级组织起来的网络,每一层的输出变量都是下一层的输入变量。上图为一个3层的神经网络,第一层成为输入层(Input Layer),最后一层称为输出层(Output Layer),中间一层成为隐藏层(Hidden Layers)。我们为每一层都增加一个偏差单位(bias unit): 即上图第1层的x_{0},第2层的a_{0}^{(2)},也就是我们之前视频里固定值为1的x_{0}

隐藏层:a_{i}^{(j)} 表示第j层的第i个神经元的激活项,激活项的意思是由一个具体神经元计算并输出的值。
意思就是第j层的第i个神经元的计算结果输出值叫做a_{i}^{(j)}

\theta^{(j)}代表从第j层映射到第j+1层时的权重的矩阵。
例如\theta^{(1)}代表从第1层映射到第2层的权重的矩阵。其尺寸为:以第j+1层的激活单元数量为行数,以第j层的激活单元数加1为列数的矩阵。例如:上图所示的\theta^{(1)}神经网络中的尺寸为 3*4,这里多出来的1列就是上图中我们自己增加的偏差单位(bias unit)。

a_{1}^{(2)}等于sigmoid激活函数(logistic激活函数)作用在线性组合上的结果。

这儿说的有点快,需要暂停然后自己分析一下:

a_{1}^{(2)} = g(\theta_{10}^{(1)}x_0 + \theta_{11}^{(1)}x_1 + \theta_{12}^{(1)}x_2 + \theta_{13}^{(1)}x_3)
a_{2}^{(2)} = g(\theta_{20}^{(1)}x_0 + \theta_{21}^{(1)}x_1 + \theta_{22}^{(1)}x_2 + \theta_{23}^{(1)}x_3)
a_{3}^{(2)} = g(\theta_{30}^{(1)}x_0 + \theta_{31}^{(1)}x_1 + \theta_{32}^{(1)}x_2 + \theta_{33}^{(1)}x_3)
h_{\theta}(x)=a_{1}^{(3)} =g(\theta_{10}^{(2)}a_{0}^{(2)} + \theta_{11}^{(2)}a_{1}^{(2)} + \theta_{12}^{(2)}a_{2}^{(2)} + \theta_{13}^{(2)}a_{3}^{(2)} )

就以分析第一个式子举例:

a_{1}^{(2)} = g(\theta_{10}^{(1)}x_0 + \theta_{11}^{(1)}x_1 + \theta_{12}^{(1)}x_2 + \theta_{13}^{(1)}x_3)

a_{1}^{(2)}表示第2层的第1个输出值。
\theta_{10}^{(1)}:上标^{(1)}表示第1层到第2层的映射,下标_{10}3\times 4矩阵的第1行第0列的元素,也就是矩阵中的坐标,\theta即权重w
其他以此类推。

课时65 模型展示Ⅱ

此节笔记参看:8.4 模型表示2
针对上面链接的部分内容做进一步解析:

这只是针对训练集中一个训练实例所进行的计算。如果我们要对整个训练集进行计算,我们需要将训练集特征矩阵进行转置,使得同一个实例的特征都在同一列里。即:
z^{(2)}=\Theta^{(1)}X^T
a^{(2)}=g(z^{(2)})

解析:因为如果我们要对整个训练集进行计算,那么整个训练集的特征X是这样排列的:
X^1=x_0^1,x_1^1,x_2^1...x_n^1
X^2=x_0^2,x_1^2,x_2^2...x_n^2
X^m=x_0^m, x_1^m, x_2^m...x_n^m
即每一个训练集数据做为一行,排成一个矩阵,这是很直觉的。
但是如果要跟\Theta矩阵做乘法运算就要把上面的X矩阵做转置,这样每一列就是一个训练集,排列变成:
X^1,X^1...X^m
这样自然可以跟\Theta矩阵做乘法运算了。

课时68 例子与直觉理解Ⅰ

用神经网络来表示and和or函数。

课时70 例子与直觉理解Ⅱ

x_1 AND \ x_2
(NOT\ x_1)\ AND\ (NOT \ x_2)
将上述的结果再通过一层x_1\ OR\ x_2,最终得到的结果相当于:x_1\ XNOR\ x_2(即异或后取反)。
这个例子主要是为了说明多层神经网络如何经过一层又一层构造出越来越复杂的函数,得到更加厉害的特征值,然后得到最终的结果。

课时71 多元分类

多分类目标最终输出一个列向量,向量中只有一个值为1其他为0,1即代表正确的类别。

章节10 神经网络参数的反向传播算法


课时72 代价函数

课时73 反向传播算法

课时74 理解反向传播

课时75 使用注意:展开参数

reshap

课时76 梯度检测

课时77 随机初始化

课时78 组合到一起

课时79 本章课程总结

本章ppt。

课时80 无人驾驶

可看可不看。

章节11 应用机器学习的建议


课时82 编程作业:正则线性回归和偏差/方差

课时83 决定下一步做什么

我们运用训练好了的模型来预测未知数据的时候发现有较大的误差,我们下一步可以做什么?

  1. 获得更多的训练样本——通常是有效的,但代价较大,下面的方法也可能有效,可考虑先采用下面的几种方法。
  2. 尝试减少特征的数量
  3. 尝试获得更多的特征
  4. 尝试增加多项式特征
  5. 尝试减少正则化程度\lambda
  6. 尝试增加正则化程度\lambda

首先怎样评估机器学习算法的性能,然后使用"机器学习诊断法"。“我们不应该随机选择上面的某种方法来改进我们的算法,而是运用一些机器学习诊断法来帮助我们知道上面哪些方法对我们的算法是有效的。
“诊断法”的意思是:这是一种测试法,你通过执行这种测试,能够深入了解某种算法到底是否有用。这通常也能够告诉你,要想改进一种算法的效果,什么样的尝试,才是有意义的。

课时84 评估假设

为了检验算法是否过拟合,我们将数据分成训练集和测试集,通常用70%的数据作为训练集,用剩下30%的数据作为测试集。很重要的一点是训练集和测试集均要含有各种类型的数据,通常我们要对数据进行“洗牌”,然后再分成训练集和测试集。
测试集评估在通过训练集让我们的模型学习得出其参数后,对测试集运用该模型,我们有两种方式计算误差:

  1. 对于线性回归模型,我们利用测试集数据计算代价函数J
  2. 对于逻辑回归模型,我们除了可以利用测试数据集来计算代价函数外:
    J_{test}{(\theta)} = -\frac{1}{{m}_{test}}\sum_\limits{i=1}^{m_{test}}\log{h_{\theta}(x^{(i)}_{test})}+(1-{y^{(i)}_{test}})\log{h_{\theta}(x^{(i)}_{test})}

误分类的比率,对于每一个测试集样本,计算:
err(h_\theta(x),y)=\left\{\begin{matrix} 1\ if\ h(x)\geq 0.5\ and\ y=0,or\ if \ h(x)<0.5\ and\ y=1) \\ 0\ otherwise \end{matrix}\right.
然后对计算结果求平均。

课时85 模型选择和训练、验证、测试集

使用60%的数据作为训练集,使用 20%的数据作为交叉验证集,使用20%的数据作为测试集
假设我们要在10个不同次数的二项式模型之间进行选择,模型选择的方法为:

  1. 使用训练集训练出10个模型
  2. 用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)
  3. 选取代价函数值最小的模型
  4. 用步骤3中选出的模型对测试集计算得出推广误差(代价函数的值)

Training error:
J_{train}(\theta) = \frac{1}{2m}\sum_\limits{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})^2

Cross Validation error:
J_{cv}(\theta) = \frac{1}{2m_{cv}}\sum_\limits{i=1}^{m}(h_{\theta}(x^{(i)}_{cv})-y^{(i)}_{cv})^2•

Test error:
J_{test}(\theta)=\frac{1}{2m_{test}}\sum_\limits{i=1}^{m_{test}}(h_{\theta}(x^{(i)}_{cv})-y^{(i)}_{cv})^2

课时86 诊断偏差与方差

高偏差和高方差的问题基本上来说是欠拟合和过拟合的问题。

训练集误差和交叉验证集误差近似时:偏差/欠拟合
交叉验证集误差远大于训练集误差时:方差/过拟合

课时87 正则化和偏差、方差

使用一些正则化方法来防止过拟合,但正则化的程度可能太高或太小,在选择\lambda的值时也需要思考与刚才选择多项式模型次数类似的问题。
我们选择一系列的想要测试的 \lambda 值,通常是 0-10之间的呈现2倍关系的值(如:0,0.01,0.02,0.04,0.08,0.15,0.32,0.64,1.28,2.56,5.12,10共12个)。

选择的\lambda 方法为:

  1. 使用训练集训练出12个不同程度正则化的模型
  2. 用12个模型分别对交叉验证集计算的出交叉验证误差
  3. 选择得出交叉验证误差最小的模型
  4. 运用步骤3中选出模型对测试集计算得出推广误差,我们也可以同时将训练集和交叉验证集模型的代价函数误差与\lambda的值绘制在一张图表上:

\lambda 较小时,训练集误差较小(过拟合)而交叉验证集误差较大
随着 \lambda 的增加,训练集误差不断增加(欠拟合),而交叉验证集误差则是先减小后增加

课时88 本章课程总结

本章ppt。

课时89 学习曲线

学习曲线来判断某一个学习算法是否处于偏差、方差问题。学习曲线是学习算法的一个很好的合理检验sanity check)。学习曲线是将训练集误差和交叉验证集误差作为训练集样本数量(m)的函数绘制的图表。

如何利用学习曲线识别高方差/过拟合:假设我们使用一个非常高次的多项式模型,并且正则化非常小,可以看出,当交叉验证集误差远大于训练集误差时,往训练集增加更多数据可以提高模型的效果。
也就是说在高方差/过拟合的情况下,增加更多数据到训练集可能可以提高算法效果。

课时90 课件资料下载方法

课时91 决定接下来做什么

  1. 获得更多的训练样本——解决高方差
  2. 尝试减少特征的数量——解决高方差
  3. 尝试获得更多的特征——解决高偏差
  4. 尝试增加多项式特征——解决高偏差
  5. 尝试减少正则化程度\lambda——解决高偏差
  6. 尝试增加正则化程度\lambda——解决高方差

神经网络的方差和偏差:
使用较小的神经网络,类似于参数较少的情况,容易导致高偏差和欠拟合,但计算代价较小。使用较大的神经网络,类似于参数较多的情况,容易导致高方差和过拟合,虽然计算代价比较大,但是可以通过正则化手段来调整而更加适应数据。
通常选择较大的神经网络并采用正则化处理会比采用较小的神经网络效果要好。
对于神经网络中的隐藏层的层数的选择,通常从一层开始逐渐增加层数,为了更好地作选择,可以把数据分为训练集、交叉验证集和测试集,针对不同隐藏层层数的神经网络训练神经网络,

课时92 课件资料下载方法

课时93 确定执行的优先级

本周以一个垃圾邮件分类器算法为例进行讨论。
为了解决这样一个问题,我们首先要做的决定是如何选择并表达特征向量x。我们可以选择一个由100个最常出现在垃圾邮件中的词所构成的列表,根据这些词是否有在邮件中出现,来获得我们的特征向量(出现为1,不出现为0),尺寸为100×1。
为了构建这个分类器算法,我们可以做很多事,例如:

  1. 收集更多的数据,让我们有更多的垃圾邮件和非垃圾邮件的样本
  2. 基于邮件的路由信息开发一系列复杂的特征
  3. 基于邮件的正文信息开发一系列复杂的特征,包括考虑截词的处理
  4. 为探测刻意的拼写错误(把watch 写成w4tch)开发复杂的算法

当我们使用机器学习时,总是可以“头脑风暴”一下,想出一堆方法来试试。

课时94 误差分析

构建一个学习算法的推荐方法为:

  1. 从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试这个算法
    2.绘制学习曲线,决定是增加更多数据,或者添加更多特征,还是其他选择
    3.进行误差分析:人工检查交叉验证集中我们算法中产生预测误差的样本,看看这些样本是否有某种系统化的趋势

误差分析并不总能帮助我们判断应该采取怎样的行动。有时我们需要尝试不同的模型,然后进行比较,在模型比较时,用数值来判断哪一个模型更好更有效,通常我们是看交叉验证集的误差。

强烈推荐在交叉验证集上来实施误差分析,而不是在测试集上。

总结一下,当你在研究一个新的机器学习问题时,我总是推荐你实现一个较为简单快速、即便不是那么完美的算法。

课时95 不对称性分类的误差评估

类偏斜情况表现为我们的训练集中有非常多的同一种类的样本,只有很少或没有其他类的样本。
例如我们希望用算法来预测癌症是否是恶性的,在我们的训练集中,只有0.5%的实例是恶性肿瘤。假设我们编写一个非学习而来的算法,在所有情况下都预测肿瘤是良性的,那么误差只有0.5%。然而我们通过训练而得到的神经网络算法却有1%的误差。这时,误差的大小是不能视为评判算法效果的依据的。

查准率Precision)和查全率Recall) 我们将算法预测的结果分成四种情况:

  1. 正确肯定True Positive,TP):预测为真,实际为真
  2. 正确否定True Negative,TN):预测为假,实际为假
  3. 错误肯定False Positive,FP):预测为真,实际为假
  4. 错误否定False Negative,FN):预测为假,实际为真

则:查准率 = TP/(TP+FP)。例,在所有我们预测有恶性肿瘤的病人中,实际上有恶性肿瘤的病人的百分比,越高越好。
查全率 = TP/(TP+FN)。例,在所有实际上有恶性肿瘤的病人中,成功预测有恶性肿瘤的病人的百分比,越高越好。
这样,对于我们刚才那个总是预测病人肿瘤为良性的算法,其查全率是0。

课时96精确度和召回率的权衡

课时97 本章课程总结

课时98 机器学习数据

一种在机器学习中的普遍共识:"取得成功的人不是拥有最好算法的人,而是拥有最多数据的人"。
为了有一个高性能的学习算法,我们希望它不要有高的偏差和方差。
因此偏差问题,我么将通过确保有一个具有很多参数的学习算法来解决,以便我们能够得到一个较低偏差的算法,并且通过用非常大的训练集来保证。
如果你有大量的数据,而且你训练了一种带有很多参数的学习算法,那么这将会是一个很好的方式,来提供一个高性能的学习算法。

章节13 支持向量机


课时99编程作业:支持向量机

课时100 本章课程总结

课时101 优化目标

支持向量机(Support Vector Machine)。与逻辑回归和神经网络相比,支持向量机,或者简称SVM,在学习复杂的非线性方程时提供了一种更为清晰,更加强大的方式。

课时102 直观上对大间隔的理解

支持向量机有时被称为大间距分类器。
在分离正样本和负样本上它显得的更好,决策边界和训练样本之间有更大的最短距离,这个距离叫做支持向量机的间距,而这是支持向量机具有鲁棒性的原因,因为它努力用一个最大间距来分离样本。
它用最大间距将样本区分开,尽管从技术上讲,这只有当参数C是非常大的时候是真的,但是它对于理解支持向量机是有益的。

课时103 大间隔分类器的数学原理

课时104 核函数1

课时105 核函数2

课时106 使用SVM

章节14 无监督学习


课时107 本章课程总结

课时108 无监督学习

将一系列无标签的训练数据,输入到一个算法中,然后我们告诉这个算法,快去为我们找找这个数据的内在结构给定数据。我们可能需要某种算法帮助我们寻找一种结构。图上的数据看起来可以分成两个分开的点集(称为簇),一个能够找到我圈出的这些点集的算法,就被称为聚类算法。

课时109 K-Means算法

K-Means算法:K-均值算法。
K-均值是最普及的聚类算法,算法接受一个未标记的数据集,然后将数据聚类成不同的组。
K-均值是一个迭代算法,假设我们想要将数据聚类成n个组,其方法为:

  1. 首先选择个随机的点,称为聚类中心(cluster centroids);
  2. 对于数据集中的每一个数据,按照距离个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类。
  3. 计算每一个组的平均值,将该组所关联的中心点移动到平均值的位置。
  4. 重复步骤2-4直至中心点不再变化。
课时110 优化目标

课时111 随机初始化

课时112 选取聚类数量

章节15 降维


课时113 编程作业:K-Means 聚类和 PCA

课时114 本章课程总结

课时115 目标 I:数据压缩

课时116 目标 II:可视化

课时117 主成分分析问题规划1

课时118 主成分分析问题规划2

课时119 主成分数量选择

课时120 压缩重

课时121 应用 PCA 的建议

章节16 异常检测



















最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容