主键

  • 总是应该定义主键
  • 主键要求:
    1. 不更新主键的值
    2. 不重用主键的值
    3. 不在主键中使用可能会更改的值

连接

  • 连接数据库: mysql -u{username} -p{password}
  • 选择表: USE tables;
  • 查看表/数据库: SHOW tables/databases;
  • 查看列: SHOW COLUMNS FROM tables;

检索数据

  • 单列: SELECT col FROM tables;
  • 多列: SELECT col1, col2 FROM tables;
  • 所有列: SELECT * FROM tables;
  • 检索不同的行: SELECT DISTINCT col FROM tables;
  • 限制结果: SELECT col FROM tables LIMIT 1,1

注意:

  1. 检索出来的数据都是未排序的,并且原始数据没有格式
  2. 一般不要使用*通配符,指出需要检索的列提高性能
  3. 通配符用处:检索未知列
  4. 不能部分使用DISTINCT
  5. LIMIT第一个参数为开始位置,第二个为检索的行数,开始位置从0开始

排序检索数据

  • 单列排序: SELECT col FROM table ORDER BY col
  • 多列排序: SELECT col1,col2 FROM table ORDER BY col1,col2
  • 指定排序方向: SELECT col FROM table ORDER BY col DESC
  • 多列指定方向: SELECT col1, col2 FROM table ORDER BY col1 DESC, col2

注意:

  1. 如果不明确排序顺序,不应假定检索出来的数据有顺序
  2. 多列时排序关键字有主次顺序之分
  3. MySQL默认为升序排序
  4. 如果想要对多个列降序排序,需要对每个列指定DESC关键字
  5. 位置: FROM ORDER BY LIMIT

过滤数据

  • 检查单个值: SELECT col FROM table WHERE col = ?
  • 检查不匹配: SELECT col FROM table WHERE col <> ?
  • 检查范围值: SELECT col FROM table WHERE col < ?
  • 空值检查: SELECT col FROM table WHERE col IS NULL
  • 组合WHERE子句:
    1. AND操作符: SELECT col FROM table WHERE col1 = ? AND col2 = ?
    2. OR操作符: SELECT col FROM table WHERE col1 = ? OR col2 = ?
    3. IN操作符: SELECT col FROM table WHERE col IN (val1, val2)
    4. NOT操作符: SELECT col FROM table WHERE col NOT IN (val1, val2)

注意:

  1. 数据检索和过滤应在数据库中完成,以提高应用的性能和减少带宽消耗
  2. AND和OR计算次序:AND会被优先计算,优先级需要使用圆括号来提升
  3. IN的功能和OR相当,但是IN的执行更快且可以包含其他SELECT语句建立子句

用通配符过滤数据

  • 百分号(%)通配符: SELECT col FROM table WHERE col LIKE 'xx%'
  • 下划线(_)通配符: SELECT col FROM table WHERE col LIKE '_ xx'

注意:

  1. 尾空格会干扰通配符匹配
  2. %不能匹配NULL的值
  3. 下划线只匹配单个字符
  4. 不要过度使用通配符

使用正则表达式过滤

  • SELECT col FROM table WHERE col REGEXP 'reg'
  • 匹配字符类
  • 定位符


注意:

  1. MySQL只支持正则的一个很小的子集
  2. 区分大小写需要在REGEXP后加BINARY关键字

计算字段

  • 拼接字段: SELECT Concat(col1, 'str', col2, 'str2') FROM table
  • 使用别名: SELECT col AS name FROM table
  • 执行算术计算: SELECT col*col2 AS name FROM table

注意:

  1. 计算字段用于格式化检索出的数据
  2. LTrim()和RTrim()函数可以去除字段左右两边空格

数据处理函数

常用文本处理函数:


常用日期处理函数:

  • 检索时间: SELECT col FROM table WHERE Date(col2) = 'xxxx-xx-xx'
  • 检索时间段: SELECT col FROM table WHERE Date(col) BETWEEN 'xxxx-xx-xx' AND 'xxxx-xx-xx'

注意:

  1. 总是应该使用4位数的年份

数值处理函数:

汇总数据

聚集函数

注意:

  1. 使用COUNT(*)计数包括NULL值,COUNT(col)则不包含NULL值

分组数据

  • 创建分组: SELECT col FROM table GROUP BY col
  • HAVING过滤分组: SELECT col, COUNT(*) FROM table GROUP BY col HAVING COUNT(*) > 2

注意:

  1. GROUP BY子句可以包含任意数目的列
  2. 建立分组时,指定的所有列都一起计算
  3. GROUP BY子句中列出的每个列都必须是检索列或有效表达式
  4. 除计算语句外, SELECT的每个列都需要在GROUP BY中给出
  5. 如果分组中有NULL值,将NULL作为一个分组返回
  6. GROUP BY子句必须出现在WHERE之后,ORDER BY之前
  7. WHERE在分组之前过滤,HAVING在分组之后过滤
  8. GROUP BY之后应该

使用子查询

  • 利用子查询进行过滤: SELECT col FROM table1 WHERE col IN (SELECT col2 FROM table2 WHERE col2=?)
  • 作为计算字段: SELECT col,(SELECT COUNT(*) FROM table2 WHERE col3=col4) FROM table1

注意:

  1. 列必须匹配,子查询SELECT和WHERE应保持相同的列
  2. 使用子查询时需要考虑效率和性能

联结表

  • 创建联结: SELECT col1, col2 FROM table1, table2 WHERE table1.col=table2.col
  • 内部联结: SELECT col1, col2 FROM table1 INNER JOIN table2 ON table1.col=table2.col
  • 外部联结: SELECT col1, col2 FROM table1 LEFT OUTER JOIN table2 ON table1.col=table2.col

注意:

  1. 在引用的列名可能出现二义性时需要使用完全限定列名
  2. 没有WHERE语句限定的结果将返回笛卡尔积
  3. WHERE为内部联结,是等值联结
  4. 可以使用表别名缩短sql语句和重复使用一张表

组合查询

  • 使用UNION: SELECT col FROM table1 WHERE col2=? UNION SELECT col FROM table1 WHERE col3=?

注意:

  1. UNION必须由两条或以上的SELECT组成
  2. UNION中的每个查询必须包含相同的列,表达式或聚集函数
  3. 列数据必须兼容
  4. UNION默认会去重,取消去重使用UNION ALL查询
  5. UNION只能使用一条排序语句出现在最后一个SELECT之后

全文本搜索

  • SELECT col FROM table WHERE Match(col) Against('text')
  • 对结果排序: SELECT col,Match(col) Against('text') AS rank FROM table

使用视图

  • CREATE VIEW view1 AS SELECT col FROM table

优点

  • 解决了特征稀疏的问题,能在非常非常稀疏数据的情况下进行预估
  • 解决了特征组合的问题
  • FM是一个通用的模型,适用于大部分的场景
  • 训练速度快,线性复杂度

开始

先附上视频的地址:机器学习算法讲堂(3):FM算法 Factorization Machine

我们首先从线性回归解法的角度来看一个特征组合的问题,如果现在数据涉及到训练集中的两个特征,那么LR就要写成:
$f(x)=w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=i+1}^nw_{ij}x_ix_j$

可以看到在这个方程中,随着特征选取的数量变多,特征组合之后的复杂度是特征数量个N相乘,这是在训练过程中不能接受的,并且线性回归的方法只能在$w_{ij}x_ix_j$不为0的情况下进行训练,对于稀疏的数据来说训练是不充分的.而FM解决的就是LR复杂度过高和对稀疏数据训练不充分的缺点.

FM的思路就是将W分解为$vv^T$,这也就是FM名字的由来,等于是因式分解W.接下来是FM的推导的过程:
首先引入辅助变量$v_i=(v_{i1},v_{i2},\cdots,v_{ik})^T\in\mathbb{R}^k,i=1,2,3\ldots,n$

已知特征矩阵W为:
$$
\begin{pmatrix} w_{11} & w_{12} & w_{13} & \cdots & w_{1n} \\ w_{21} & w_{22} & w_{23} & \cdots & w_{2n} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ w_{n1} & w_{n2} & w_{n3} & \cdots & w_{nn} \\ \end{pmatrix}
$$
V矩阵为:
$$
\begin{pmatrix} v_{11} & v_{12} & v_{13} & \cdots & v_{1k} \\ v_{21} & v_{22} & v_{23} & \cdots & v_{2k} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ v_{n1} & v_{n2} & v_{n3} & \cdots & v_{nk} \\ \end{pmatrix}
$$
且有结论:当k足够大时,对于任意对称正定实矩阵$w\in\mathbb{R}^{n\times n}$,均存在实矩阵$v\in\mathbb{R}^{n\times k}$使得$w=vv^T$

这样一来,我们只要找到一个$vv^T=w$就可以解决这个问题了,而分解成$vv^T$的优势在于有效的降低了算法的复杂度,下面是对FM算法的求解:

根据上面的分解,可以将FM公式写为:
$$
y=w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{j=i+1}^n<v_i,v_j>x_ix_j, <v_i,v_j>=\sum_{f=1}^kv_{i,f}\cdot v_{j,f}
$$
这里主要需要求解的就是最后一项:
$$
\begin{split} &\sum_{i=1}^{n-1}\sum_{j=i+1}^n<v_i,v_j>x_ix_j \\ =&\frac {1} {2}\sum_{i=1}^n\sum_{j=1}^n<v_i,v_j>-\frac {1} {2}\sum_{i=1}^n<v_i,v_i>x_ix_i \text{,把j化成i,需要减去重复的部分} \\ =&\frac {1} {2} \left( \sum_{i=1}^n\sum_{j=1}^n\sum_{f=1}^kv_{i,f}v_{j,f}x_ix_j-\sum_{i=1}^n\sum_{f=1}^kv_{i,f}v_{i,f}x_ix_i \right) \text{,把上面的等式代入进来} \\ =&\frac {1} {2} \sum_{f=1}^k \left( \left( \sum_{i=1}^nv_{i,f}x_i \right) \left( \sum_{j=1}^nv_{j,f}x_j \right)-\sum_{i=1}^nv_{i,f}^2x_i^2 \right) \text{,提出公共的求和部分} \\ =&\frac {1}{2} \sum_{f=1}^k \left( \left( \sum_{i=1}^nv_{i,f}x_i \right)^2-\sum_{i=1}^nv_{i,f}^2x_i^2 \right) \text{,前面2项除了下标的i,j不同之外是一样的,所以合并} \\ \end{split}
$$
我们可以看到公式化简到最后,复杂度就只和求和符号上的k,n相关了,所以复杂度可以简单的记为O(nk),但是这已经比之前的线性回归的解法复杂度低了很多了,这可以视为是线性的复杂度.

下面看一下FM的梯度的计算,我们对$w_0,w_i,v_i$分别求偏导可以写为:
$$
\frac {dy} {d\theta}= \begin{cases} 1, & \text{if $\theta=w_0$} \\ x_i, & \text{if $\theta=w_i$} \\ x_i\sum_{j=1,j\neq i}^nv_{j,f}x_j & \text{if $\theta=v_{i,f}$} \\ \end{cases}
$$
最后一个公式可以化为:
$$
x_i\sum_{j=1,j\neq i}^nv_{j,f}x_j = x_i\sum_{j=1}^nv_{j,f}x_j-v_{i,f}x_i^2
$$
我们可以看到这个梯度计算的公式中,计算复杂度也只和n相关也就是说:复杂度是O(n)!相比于简单的LR动不动的N方的复杂度来说,FM的复杂度可以说是相当的低了.

拓展

这里就只是先列举一下FM的一些拓展使用:

  • FFM
  • DeepFM
  • DCN
  • xDeepFM

下面就放几个图片吧(这次是自己截图放的图床)
DeepFM:
DeepFM
xDeepFM:
xDeepFM

贴一下论文的地址:
Factorization Machines

xDeepFM: Combining Explicit and Implicit Feature Interactions for Recommender Systems

开始

在一个普通的周末打开哔哩哔哩刷新动态的时候突然看到qsc投稿了视频的我是表示震惊的!当看到标题是机器学习算法讲堂的时候,我知道:是时候了,是时候开始学一点机器学习了,那么这也算是最近周末的常驻项目之一了.既然看了视频并且手推了一遍,肯定是要搞个大新闻的,那么就开个博客记录一下自己的笔记吧.

先来贴一下qsc视频的地址:
机器学习算法讲堂(2):线性回归推导
机器学习算法讲堂(2.1):最大似然与线性回归

线性回归

首先允许我再盗一张图:

这是一个非常经典的二维的线性回归的图片.我们的任务就是找到这样一条直线,使得这条直线到平面上所有的点的距离之和最小,写成函数就是这样:
$ f(x)=w_0+w_1x_1+w_2x_2+\cdots=w_nx_n = w^Tx, x\in\mathbb{R}^d,y\in\mathbb{R} $

判断这个函数的好坏我们就定义一个损失函数(loss function)如下(最小二乘法):
$ E=\frac {1} {N}\sum_{i=1}^N(f(x_i)-y_i)^2 $
解释:对每个$x_i$应用预测函数的值f($x_i$)减去数据集中的正确值的差再平方,求1…N所有误差的和再除以N取平均

定义W为使得E最小时的参数:W=argminE,然后我们可以把这个问题转化为求E的导数,找到E的导数为0的点就是E最小的点
先将E化为矩阵的表示形式(这里的x和y都是矩阵的形式):
$$
\begin{split}
E &= \begin{Vmatrix} Xw-y \end{Vmatrix}^2 \\
&=(Xw-y)^T(Xw-y)
\end{split}
$$

接下来对E求导(左导右不导加上右导左不导):
$$
\begin{split}
dE&= (Xdw)^T(Xw-y)+(Xw-y)^TXdw \\
&=2(Xw-y)^TXdw \\
\frac {dE^T} {dw}&=(2(Xw-y)^TX)^T \\
&=2X^T(Xw-y) \Rightarrow \nabla
\end{split}
$$

我们可以把$\nabla$当做是训练的梯度,当$2X^T(Xw-y)=0$的时候w可以取到最小,转换一下:
$w=(X^TX)^{-1}X^Ty$
当$X^TX$可逆的时候就可以直接求解,不可逆的时候就需要使用梯度下降的方法来训练使得E收敛到最小获得w的值.
梯度下降:$w(t+1)=w(t)-\lambda\nabla$,$\lambda$为梯度下降的步长.

最大似然

还是回到上面的图片中,在我们用函数来拟合这组数据的时候,因为无法完美的拟合数据,所以我们假设有我们没有观察到的因素存在导致我们的拟合函数存在误差,而这个拟合函数所缺失的不可解释的那部分误差就是直线到数据点之间的距离.
同时我们换个角度来看这个数据集,既然这些点被我们观测到了,就说明这些点被我们观测到的概率是最大的,由此可以推出,我们可以寻找一个函数,使得我们能够观测到这些点的概率最大,那我们也就找到了对些数据最好的拟合.

似然函数推导

假定存在一个数据集D=$\lbrace(x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n)\rbrace$
我们定义函数$y_i=f(x_i)+\varepsilon_i,\varepsilon_i为不能完全解释的误差$
问题就转化成了:现在我们有N个f(x)函数,我们要评估哪个模型最有可能产生这一组数据,用概率来表示就是:
$P(D|x,\theta)=P(y_1,y_2,y_3,\cdots,y_N|x_1,x_2,x_3,\cdots,x_N,\theta)$
假设数据之间是相互独立的(概率相乘):
$P(y_1,y_2,y_3,\cdots,y_N|x_1,x_2,x_3,\cdots,x_N,\theta)=\prod_{j=1}^N P(y_j|x_j,\theta)$
我们的似然函数也就是:$likelihood(\theta)=\prod_{j=1}^N P(y_j|x_j,\theta)$
因为对于数据集D来说x,y已经确定所以可以将概率转换如下:
$P(y_i|x_i,\theta)=P(y_i|f(x_i)+E)=P(y_i-f(x_i)|E)$
可以看到:对于任意的x,y来说概率就和模型的预测值和实际值之间的误差E的分布相关了.

最大似然和线性回归

根据我们之前的定义:$y_i=f(x_i)+\varepsilon_i$ 我们可以推出:$\varepsilon_i=y_i-w^Tx_i$ (也就是前面线性回归推导中使用的误差)
我们假设Y服从均值为$w^Tx$ ,方差为1的分布:
$$
P(Y|x)=P(\varepsilon|x)=\frac {1} {\sqrt{2\pi}\times e^{\frac {-\varepsilon^2} {2}}}
$$
将上面的$\varepsilon_i=y_i-w^Tx_i$ 代入公式:
$$
P(Y|x)=P(\varepsilon|x)=\frac {1} {\sqrt{2\pi}\times e^{\frac {-(y_i-w^Tx_i)^2} {2}}}
$$
由于误差符合正态分布,我们将概率代入似然函数中并且对似然函数取log:
$$
likelihood(\theta)=\log \prod_{j=1}^N \frac {1} {\sqrt{2\pi}\times e^{\frac {-(y_i-w^Tx_i)^2} {2}}}
$$
化简得到:
$$
N\log(\frac {1} {\sqrt{2\pi}})+\frac {\sum_{i=1}^N-(y_i-w^Tx_i)^2} {2}
$$
去掉前面的常数项和后面的常系数之后可以化简为:
$$\sum_{i=1}^N-(y_i-w^Tx_i)^2$$
我们要使得概率最大也就是使得似然函数最大:
$$max\sum_{i=1}^N-(y_i-w^Tx_i)^2$$
也就是(去掉负号):
$$min\sum_{i=1}^N(y_i-w^Tx_i)^2$$
完成!是不是发现这和最小二乘法给出的公式(loss function)是一样的?因为最小二乘法是最大似然解法的一种特殊情况.
从最大似然解法的推导中我们可以看到:均方误差最小化求解线性回归和假设预测符合高斯分布然后利用最大似然估计求解线性回归得到的结果是相同的

总结

虽然是最简单的线性回归的推导,但是从概率的角度利用最大似然来推出loss function的那一刻还是感觉到:数学真炫酷啊~
之前看机器学习的时候感觉数学公式看到就很头疼,但是现在自己硬着头皮推一遍之后发现并没有那么复杂而且通过这种硬盒的方式来学机器学习的算法是获益匪浅.最后再说一句:qsc的视频我是期期都看啊~

0%