2019-05-23 01:07:19 titing3539 阅读数 63

用梯度下降手写线性回归(只用numpy 、pandas)

  • 用梯度下降方法预测PM2.5的值
    李宏毅机器学习中的作业1 ,这里为了简化流程,突出方法,只用了train.csv数据。
    简单说一下要干嘛:就是有很多条观测数据,每一条数据包含了24小时的观测数据,通过这些数据,预测未来PM2.5的值。

这里继续简化问题,用前9小时的数据预测第10个小时的值:

import pandas as pd
import numpy as np

train_data = pd.read_csv('train.csv',encoding='utf-8')  #utf-8编码 
train_data.insert(3, 'b', 1)    #  插入一列都为1的数, bias * 1  所有参数统一看成 w
a1 =  train_data[train_data['observation']=='PM2.5'].iloc[:-50,3:13] #用来训练参数 w
a2 =  train_data[train_data['observation']=='PM2.5'].iloc[-50:,3:13] # 后50行用来算下某参数下的error
a1_x = a1.values[:,:-1]   #前9个小时数据
a1_x_array = a_x.astype(np.float)    
a1_y = a1.values[:,-1]    #第10个小时数据
a1_y_array = a_y.astype(np.float)

a2_x = a2.values[:,:-1]
a2_x_array=a2_x.astype(np.float)
a2_y = a2.values[:,-1]
a2_y_array=a2_y.astype(np.float)

梯度下降实现,直接撸:

在这里插入图片描述

#  线性回归 梯度下降
def update_w(dataMatin,label):
    dataMatrix = np.mat(dataMatin)    # m 样本量 ,n 特征数量  (m , n)
    labelMatrix = np.mat(label).transpose()   # (m , 1)
    m, n = np.shape(dataMatrix)      
    alpha = 0.0000001        # 学习率
    max_cycle = 100000000    #迭代次数
    w = np.ones((n,1))          # w 初始值为1 
    for i in range(max_cycle):
        h = dataMatrix*w           # (m ,n) × (n ,1) = (m , 1)    x*w
        err = (labelMatrix - h)   #(m ,1)
        w = w + alpha * dataMatrix.transpose()*err    # (n,m)×(m,1) = (n , 1)
    return w 


# 平方差的和 作为 error
def Error(y_label, y_fitting):   
    return np.sum(np.square(y_label,y_fitting))


# 测试集数据代入 训练好参数w的线性函数中的误差
def model_error(dataMatIn, label, w):
    dataMatrix = np.mat(dataMatIn)
    labelMatrix = np.mat(label).transpose()
    h = (dataMatrix*w)
    error = Error(labelMatrix, h)        #(m , 1)
    return error

最后,可调整 alpha 值最大迭代次数优化梯度下降。

2019-05-21 14:02:10 weixin_44049128 阅读数 177

本博文主要是完成李宏毅机器学习HW1作业

作业连接:https://ntumlta2019.github.io/ml-web-hw1/

作业规则

所有代码必须用python3.6编写

允许所有python标准库(例如sys,csv,time)
numpy> = 1.14
scipy == 1.2.1
pandas == 0.24.1。

作业要求

  • 使用adagrad 线性回归梯度下降
    • 选取合适的特征
    • 实施线性回归
    • 使用Adagrad进行梯度下降:动态调整学习率
    • 预测PM2.5的值

作业进行

1 提取特征

在这里插入图片描述

数据介绍:本次使用丰原站的观测记录,分成训练集跟测试集,训练集是丰原站每个月的前20天所有资料,测试集則是从丰原原站剩下的資料中取样出來。
train.csv:每个月前20天每个小时的气象资料(每小时有18种测试内容)。共12个月。
test.csv:从剩下的资料当中取样出连续的10小时为一笔,前九小时的所有观测数据当作feature,第十小时的PM2.5当作answer。一共取出240笔不重复的测试集,请根据feature预测这240笔的PM2.5。

2 伪代码

  1. 处理数据,提取特征
train_x		# 前9小时数据
train_y		# 第10小时PM2.5数据

for i in all the given data:
	sample every10 hrs:
		train_x.append(previous 9-hr data)
		train_y.append(the value of 10th-hr pm2.5)
		add a bias term to every data in train_x
  1. 实施线性回归
    在这里插入图片描述
    在这里插入图片描述
Declare weight vector, initial lr ,and iteration	# 声明权重w 初始化学习率lr 以及训练轮数
for i_th iteration :
	y’ = the product of train_x  and weight vector
	Loss = y’ - train_y
	gradient = 2 * np.dot((train_x)’, L )
	prev_gra += gra**2
	 ada = np.sqrt(prev_gra)
	weight vector -= learning rate * gradient / ada
  1. 预测PM2.5
read test_x.csv file	# 读取数据
for every 18 rows :
	test_x.append([1])
	test_x.append(9-hr data)
	test_y = np.dot(weight vector, test_x)

3 代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas as pd
import numpy as np

# 获取训练数据
def get_train_data():
    train_data = pd.read_csv("train.csv")
    '''
    获取PM2.5数据:
    train_data['observation']表示取csv数据中的“observation”列
    返回:序号 污染物种类
    train_data[train_data['observation'] == 'PM2.5']表示获取污染物中PM2.5的数据
    iloc[:, 3:]表示取第3列之后的列以及所有行的数据
    '''
    data_pm25 = train_data[train_data['observation'] == 'PM2.5'].iloc[:, 3:]
    x_list=[]
    y_list=[]
    for i in range(15):
        # 获取前9小时pm2.5数据作为输入feature(并非只有0-8 1-9 2-10都可以)
        x = data_pm25.iloc[:,i:i + 9]
        x.columns = np.array(range(9))
        # 获取第10小时pm2.5数据作为label
        y = data_pm25.iloc[:, i + 9]
        y.columns=[1]
        x_list.append(x)
        y_list.append(y)

    x_data = pd.concat(x_list)
    y_data = pd.concat(y_list)
    
    X = np.array(x_data, float)
    # np.c_按行连接矩阵 给输入数据加bias
    X = np.c_[np.ones((X.shape[0], 1)), X]
    Y = np.array(y_data, float)
    return X, Y


def get_test_data():
    test_data = pd.read_csv("test.csv")
    data_pm25 = test_data[test_data['AMB_TEMP'] == 'PM2.5'].iloc[:, 2:]
    X = np.array(data_pm25, float)
    X = np.c_[np.ones((X.shape[0], 1)), X]
    return X


'''
Adagrad梯度下降的公式为:
w^{t+1} = w^t- eta/sqrt{sum^t_{i=0}(g^i)^2}g^t
'''
class AdaGrad():
    def __init__(self, lr=10, epochs=10000):
        '''
        :param lr: 学习率
        :param epochs: 训练轮数
        '''
        self.lr = lr
        self.epochs = epochs


    def fit(self, x, y):
        m = y.size
        w = np.zeros(x.shape[1])
        s_grad = np.zeros(x.shape[1])
        cost = []
        for j in range(self.epochs):
            # Model 模型
            y_hat = np.dot(x, w)
            # Error 误差
            error = y_hat - y
            # Gradient 梯度
            grad = np.dot(x.transpose(), error) * 2
            s_grad += grad ** 2
            ada = np.sqrt(s_grad)
            w -= self.lr * grad / ada
            J = 1.0 / (m) * (np.sum(np.square(y_hat - y)))
            cost.append(J)
        return w, cost


X_train, y_train = get_train_data()
X_test = get_test_data()

gd = AdaGrad()
w, cost = gd.fit(X_train, y_train)
print(w, cost[-1])

# 预测
h = np.dot(X_test,w)
real = pd.read_csv('answer.csv')
erro = abs(h - real.value).sum() / len(real.value)
print('平均绝对值误差',erro)

以上。

2019-07-07 23:19:15 wangwei19871103 阅读数 98

李宏毅机器学习系列-循环伸进网络RNN


最近做语音研究,可能要用到RNN,所以把李宏毅老师的RNN看了下,顺便做下记录吧,方便以后自己回顾和大家学习。前面有偏比较直觉的讲RNN的,有兴趣的也可以看下。

神经网络可能也需要记忆

在这里插入图片描述
首先来看个例子,加入我们有句话,需要提取出两个slot(可以看做特征吧),一个是目的地,一个是到达时间,比如上面这句话,目的地是Taipei,达到时间是November 2nd2^{nd} 。我们把这句话输入到一个普通的神经网络,我们希望他能将这两个slot输出:
在这里插入图片描述
神经网络只能接受数字呀,所以我们得把单词转化成向量,比如可以用类似one-hot的这种:
在这里插入图片描述
也可以用另外的,都是编码的方法,就不多做介绍了:
在这里插入图片描述
我们希望输如台北的时候,它是目的概率越大越好,但是貌似普通的神经网络遇到下面这种情况就无法很好工作了,比如两个句子,一个是到达,一个是离开,每个词都做了编码,比如目的地,时间,还有其他的单词,这里Taipei的特征应该是不同的,但是对于这种神经网络来说,你给它的输入是一样的,它就给你相同的输出,这样第二句话也会把Taipei认为是目的地,其实是出发地。也就是说,要么都是目的地,要么都是出发地,没办法让他一会儿出发地,一会儿目的地:
在这里插入图片描述
那怎么解决这个问题呢,我们人类当然知道啦,看上下文嘛,前面不是有个词,arrvie和leave嘛。是呀,我们能看到,但是神经网路看不到呀,他又不会去前面看看是什么词,所以我们想到要给他加点记忆,让他能记住前面的词,可能会影响后面的判断,于是就提出了让神经网路有记忆。于是就提出了RNN。

RNN简介

在这里插入图片描述
上图就是简单的RNN,我们将中间层的输出保存下来,作为下一个输入的一部分,这样前面的输入就可以对后面的输出造成影响啦。举个简单的例子:
在这里插入图片描述
我们的输入序列如图,w=1,b=0,激活函数为线性的,可以看到输入为[1,1]的时候记忆区的数据为0,隐藏层输出为[2,2],最后输出为[4,4].我们继续:
在这里插入图片描述
前一次输入后,隐藏层的结果[2,2]被保存到了记忆区里,这次又是输入[1,1],但是此时记忆区有非0数据,也当作输入的一部分,新的隐藏层结果为[6,6],输出为[12,12],可以看到,相同的输入产生了不同的结果。我们继续:
在这里插入图片描述
前一次输入后,隐藏层的结果[6,6]被保存到了记忆区里,这次是输入[2,2],此时记忆区有非0数据,也当作输入的一部分,新的隐藏层结果为[16,16],输出为[32,32].当然如果你把上面输入顺序换了,输出的结果是不同的,如果是[2,2],[1,1],[1,1][2,2],[1,1],[1,1]那结果应该是[8,8],[20,20],[44,44].其实就是这样把隐藏层的输入接到下一个输入上,不停循环,就是循环神经网络RNN。
在这里插入图片描述
上图就是同一个神经网络在不同的时间点被循环使用了。如此一来,判断Taipei应该是哪个特征的时候就会根据前一个单词来做出选择,因为前面是arrive,所以Taipei大概率是目的地。所以输入同个词,输出不同的结果就可以实现啦:
在这里插入图片描述
上面只是2次循环,当然可以有很多次循环啦,即是深层RNN啦:
在这里插入图片描述

当然RNN里的网络架构也有不同,比如一种是隐藏层当做记忆,一种是输出当做记忆:
在这里插入图片描述
还有一种是双向的,也就是上下文啦,比如你要做英语完形填空可能需要吧。
在这里插入图片描述

LSTM

在这里插入图片描述
LSTM就是长一点的短期记忆,前面介绍的简单的那种,基本就是保存了上一个时间的记忆,可能马上又被替换成新的了,LSTM是可以根据需要保存了时间稍微长一点的。当然最简单的RNN也可能出现梯度消失和梯度爆炸问题,最开始的记忆因为前向传播被乘以N个权重,反向传播链式法则最后传到前面的梯度可能是很小,也可能很大。LSTM的一个模块包括4个输入,1个输出,1个记忆单元。
4个输入为:
输入,此刻输入的单词
输入门,控制是否要使用输入
遗忘门,控制是否要把以前的记忆给抹去
输出门,控制是否将结果输出

具体结构为:
在这里插入图片描述
所有控制门都会进过sigmoid激活函数,以便于输出0或者1,乘以相应的输入,就可以进行控制。
简单的来说就是,我有个输入x,要跟输入门相乘,输入门是1,就让我通过了,输入时0,就是不通过。通过了后到了记忆单元,记忆单元首先会根据将老记忆c跟遗忘门的输入相乘,也是一样,遗忘门是1,那记忆保留了,遗忘门是0,记忆丢失。将输入与老记忆相加起来,作为新的记忆=输入+老记忆。然后通过激活函数走到输出的关口,输出关口做的事也一样,输出关口是1,就输出新值,否则就输出0。
当然事实上也不都是0,1,0到1之间也可以,可以理解为权重,0就是不重要,全部丢弃,1表示很重要,全部都要。

其实RNN只是代替的普通神经网络的神经元:
在这里插入图片描述
因为LSTM有4个输入,所以参数是普通的4倍:
在这里插入图片描述
我们取出一个来看看他怎么运行的:
在这里插入图片描述
输入的向量xtx^t通过4个权重矩阵会被转换成4个向量,然后不同的维度输入到不同的LSTM模块里,每个模块里的cell会保留一个数值,合起来就是向量ct1c^{t-1}。连起来看就是这样的:
在这里插入图片描述
实际上他会把前一刻的记忆和输出也当做这一刻的输入来一起控制输入的4个向量。

然而真正的LSTM可能还会叠很多层:
在这里插入图片描述
看起来很复杂是把,其实你弄明白了1个LSTM的原理,就可以懂啦,其实这个图看起来也就是上下个隐层层,1层里面才2个神经元哦。
在这里插入图片描述

总结

RNN就是让神经网络有记忆,以便需要有关联上下文的时候可以起作用,LSTM是一种RNN,可以保持记忆一定的时间。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵,图片来自李宏毅课件,侵删。

2019-05-31 01:54:47 titing3539 阅读数 41

1、LR损失函数和梯度下降

在这里插入图片描述
一般线性函数的损失函数是平方损失函数,LR求最大似然估计是因为sigmoid函数求导后无法保证是凸函数,在优化的过程中可能得到的是局部最小值,而非全局最优。取对数是方便求导。
在这里插入图片描述
损失函数除以m这一因子并不改变最终求导极值结果,通过除以m可以得到平均损失值避免样本数量对于损失值的影响

2、Softmax原理

顾名思义,softmax由两个单词组成,其中一个是max。对于max我们都很熟悉,比如有两个变量a,b。如果a>b,则max为a,反之为b。
另一个单词是soft。max存在的一个问题是什么呢?如果将max看成一个分类问题,就是非黑即白,最后的输出是一个确定的变量。更多的时候,我们希望输出的是取到某个分类的概率,或者说我们希望分值大的那一项被经常取到,而分值较小的那一项也有一定的概率被取到,所以我们就应用到了soft的概念,即最后的输出是每个分类被取到的概率。下面的图就很容易理解Softmax原理:
在这里插入图片描述
假设有一个数组V,Vi表示V中的第i个元素,那么这个元素的softmax值为: 在这里插入图片描述
该元素的softmax值,就是该元素的指数与所有元素指数和的比值。

3、Softmax损失函数和梯度下降

softmax损失函数用的是交叉熵函数,主要是由于这个求导结果比较简单,易于计算,并且交叉熵解决某些损失函数学习缓慢的问题
在这里插入图片描述
在这里插入图片描述

2017-03-28 19:14:11 xzy_thu 阅读数 10164

台湾大学李宏毅老师的机器学习课程是一份非常好的ML/DL入门资料,李宏毅老师将课程录像上传到了YouTube,地址:NTUEE ML 2016
这篇文章是学习本课程第1-3课所做的笔记和自己的理解。


Lecture 1: Regression - Case Study

machine learning 有三个步骤,step 1 是选择 a set of function, 即选择一个 model,step 2 是评价goodness of function,step 3 是选出 best function。

regression 的例子有道琼斯指数预测、自动驾驶中的方向盘角度预测,以及推荐系统中购买可能性的预测。课程中的例子是预测宝可梦进化后的CP值。

一只宝可梦可由5个参数表示,x=(x_cp, x_s, x_hp, x_w, x_h)。我们在选择 model 的时候先选择linear model。接下来评价goodness of function ,它类似于函数的函数,我们输入一个函数,输出的是how bad it is,这就需要定义一个loss function。在所选的model中,随着参数的不同,有着无数个function(即,model确定之后,function是由参数所决定的),每个function都有其loss,选择best function即是选择loss最小的function(参数),求解最优参数的方法可以是gradient descent。

gradient descent 的步骤是:先选择参数的初始值,再向损失函数对参数的负梯度方向迭代更新,learning rate控制步子大小、学习速度。梯度方向是损失函数等高线的法线方向。

gradient descent 可能使参数停在损失函数的局部最小值、导数为0的点、或者导数极小的点处。线性回归中不必担心局部最小值的问题,损失函数是凸的。

在得到best function之后,我们真正在意的是它在testing data上的表现。选择不同的model,会得到不同 的best function,它们在testing data 上有不同表现。复杂模型的model space涵盖了简单模型的model space,因此在training data上的错误率更小,但并不意味着在testing data 上错误率更小。模型太复杂会出现overfitting。

如果我们收集更多宝可梦进化前后的CP值会发现,进化后的CP值不只依赖于进化前的CP值,还有其它的隐藏因素(比如宝可梦所属的物种)。同时考虑进化前CP值x_cp和物种x_s,之前的模型要修改为
if x_s = pidgey: y = b_1 + w_1 * x_cp
if x_s = weedle: y = b_2 + w_2 * x_cp
if x_s = caterpie: y = b_3 + w_3 * x_cp
if x_s = eevee: y = b_4 + w_4 * x_cp
这仍是一个线性模型,因为它可以写作
y =
b_1 * δ(x_s = pidgey) + w_1 * δ(x_s = pidgey) * x_cp +
b_2 * δ(x_s = weedle) + w_2 * δ(x_s = weedle) * x_cp +
b_3 * δ(x_s = caterpie) + w_3 * δ(x_s = caterpie) * x_cp +
b_4 * δ(x_s = eevee) + w_4 * δ(x_s = eevee) * x_cp
上式中的粗体项都是linear model y = b + Σw_i * x_i 中的feature x_i
这个模型在测试集上有更好的表现。如果同时考虑宝可梦的其它属性,选一个很复杂的模型,结果会overfitting。

对线性模型来讲,希望选出的best function 能 smooth一些,也就是权重系数小一些,因为这样的话,在测试数据受噪声影响时,预测值所受的影响会更小。
所以在损失函数中加一个正则项 λΣ(w_i)^2
越大的λ,对training error考虑得越少。
我们希望函数smooth,但也不能太smooth。
调整λ,选择使testing error最小的λ。

Lecture 2: Where does the error come from?

error有两种来源,分别是bias和variance,诊断error的来源,可以挑选适当的方法improve model。

以进化前的宝可梦为输入,以进化后的真实CP值为输出,真实的函数记为f^。(在上帝视角才能知道f^
从训练数据,我们找到 f f是对f^的一个估计。

bias and variance

简单模型,variance小。复杂模型,variance大。(简单模型更少受训练数据影响。复杂模型会尽力去拟合训练数据的变化。)
bias代表f¯f^ 的距离。简单模型,bias大。复杂模型,bias小。
simple model的model space较小,可能没有包含target。

在underfitting的情况下,error大部分来自bias。
在overfitting的情况下,error大部分来自variance。

如果model连训练样本都fit得不好,那就是underfitting, bias大。
如果model可以fit训练样本,但是testing error大,那就是overfitting, variance大。

在bias大的情况下,需要重新设计model,比如增加更多的feature,或者让model更complex。而此时more data是没有帮助的。
在variance大的情况下,需要more data,或者regularization。more data指的是,之前100个f,每个f抓10只宝可梦,现在还是100个f,每个f抓100只宝可梦。more data很有效,但不一定可行。regularization希望曲线平滑,但它可能伤害bias,造成model space无法包含target f^

在选择模型时,要考虑两种error的折中,使total error最小。

不应该这样做:
what you should NOT do

因为这样做,在public testing set上的error rate,并不代表在private testing set上的error rate。
应该采用cross validation的方法!
cross validation

training set分成training setvalidation set,在training set上训练model 1-3,选择在validation set 上error rate最小的model。
如果嫌training set中data少的话,可以在确定model后在全部training data上再train一遍该model。
这样做,在public testing set上的error rate才会代表在private testing set上的error rate。
不能用public testing set去调整model。

N折交叉验证
N-fold cross validation

training set分成N折,每次只有一折作为validation set,其它折作为training set,在各model中选择N次训练得到的N个validation error rate的均值最小的model。

Lecture 3: Gradient Descent

gradient descent

Tip 1: Tuning your learning rates

在用梯度下降时要画出loss随更新参数次数的曲线(如下图),看一下前几次更新参数时曲线的走法如何。
loss ~ Number of parameters updates

调整学习率的一个思路是:每几个epoch之后就降低学习率(一开始离目标远,所以学习率大些,后来离目标近,学习率就小些),并且不同的参数有不同的学习率。

Adagrad

Adagrad

Adagrad2

如何理解Adagrad的参数更新式子呢?以一元二次函数为例,参数更新的best step是
best step

在参数更新式子中,gt 代表first derivative,分母中的根号项反映了second derivative(用first derivative去估计second derivative)。

Tip 2: Stochastic Gradient Descent

SGD让训练过程更快。普通GD是在看到所有样本(训练数据)之后,计算出损失L,再更新参数。而SGD是每看到一个样本就计算出一个损失,然后就更新一次参数。

Tip 3: Feature Scaling

如果不同参数的取值范围大小不同,那么loss函数等高线方向(负梯度方向,参数更新方向)不指向loss最低点。feature scaling让不同参数的取值范围是相同的区间,这样loss函数等高线是一系列共圆心的正圆,更新参数更容易。
feature scaling的做法是,把input feature的每个维度都标准化(减去该维度特征的均值,除以该维度的标准差)。

Gradient Descent的理论推导(以两个参数为例)

Taylor Series

Taylor Series2

约等式的成立需要the red circle is small enough这个条件,如果η 没有设好,这个约等式可能不成立,从而loss不会越来越小。

也可以考虑Taylor Series中的二阶项,要多很多运算,一般不划算。


李宏毅机器学习课程笔记

李宏毅机器学习课程笔记1:Regression、Error、Gradient Descent
李宏毅机器学习课程笔记2:Classification、Logistic Regression、Brief Introduction of Deep Learning
李宏毅机器学习课程笔记3:Backpropagation、”Hello world” of Deep Learning、Tips for Training DNN
李宏毅机器学习课程笔记4:CNN、Why Deep、Semi-supervised
李宏毅机器学习课程笔记5:Unsupervised Learning - Linear Methods、Word Embedding、Neighbor Embedding
李宏毅机器学习课程笔记6:Unsupervised Learning - Auto-encoder、PixelRNN、VAE、GAN
李宏毅机器学习课程笔记7:Transfer Learning、SVM、Structured Learning - Introduction
李宏毅机器学习课程笔记8:Structured Learning - Linear Model、Structured SVM、Sequence Labeling
李宏毅机器学习课程笔记9:Recurrent Neural Network
李宏毅机器学习课程笔记10:Ensemble、Deep Reinforcement Learning

没有更多推荐了,返回首页