Tag Archives: Neural Network

Repost of my KDD Cup 2018 summary

I finished 30th place at this year's KDD CUP. I still remember back to 2015, when I was very rusty with coding and tried to attempt that years' KDD cup with my potato laptop Lenovo U310. I did not know what I was doing, all I did is trying to throw data into XGBoost and my performance then is a joke. I see myself became more and more capable of comming up with ideas and implement them out during these two years. And below is a repost of my summary to KDD 2018.

Hooray~! fellow KDD competitors. I entered this competition on day 1 and very quickly established a reasonable baseline. Due to some personal side of things, I practically stopped improving my solutions since the beginning of May. Even though my methods did not work really well compared to many top players in phase 2, but I think my solution may worth sharing due to it is relative simplicity. I did not touch the meo data at all, and one of my models is just calculating medians.

Alternative data source

For new hourly air quality data, as shared in the forum, I am using this for London and this for Beijing instead of the API from the organizer.

Handling missing data

I filled missing values in air quality data with 3 steps:

  1. Fill missing values for a station-measure combo based on the values from other stations.
    To be specific: I trained 131 lightgbm regressors for this. If PM2.5 reading on 2:00 May 20th is missing for Beijing aotizhongxin station, the regressor aotizhongxin_aq-PM2.5 will predict this value based on known PM2.5 readings on 2:00 May 20th from 34 other stations in Beijing.
    I used thresholds to decide whether to do this imputation or not. If more than the threshold number of stations also don't have a reading, then skip this step.
  2. Fill the remaining missing values by looking forward and backward to find known values.
  3. Finally, replace all remaining missing values by overall mean value.

Approaches

1. median of medians

This is a simple model that worked reasonably well in this Kaggle competition.

To predict PM2.5 reading on 2:00 May 20th for aotizhongxin, look back for a window of days history, calculating the median 2:00 PM2.5 readings from aotizhongxin in that window. You do this median calculation exercise for a bunch of different window sizes to obtain a bunch medians. The median value of those medians is used as the prediction.

Intuitively this is just an aggregated yesterday once more. With more larger windows in the collection, the model memorizes the long-term trend better. The more you add in smaller windows, the quicker the model would respond to recent events.

2. facebooks' prophet

This is practically even simpler than the median of medians. I treated the number of days history I throw at it and the model parameters changepoint_prior_scalen_changepoints as main hyperparameters and tweaked them. I did a bit work to parallelizing the fitting process for all the station-measure combos to speed up the fitting process, other than that, it is pretty much out of the box.

I tried to use holiday indicator or tweaking other parameters of the model and they all degrade the performance of the model.

3. neural network

My neural network is a simple feed-forward network with a single shortcut, shamelessly copied the structure from a senior colleague's Kaggle solution with tweaked hidden layer sizes.
The model looks like this:
nn_plot

The input to the neural network are concatenated (1) raw history readings, (2) median summary values from different window_sizes, and (3) indicator variables for the city, type of measure.

The output layer in the network is a dense layer with 48 units, each corresponding to an hourly reading in the next 48 hours.

The model is trained directly using smape as loss function with Adam optimizer. I tried standardizing inputs into zero mean and unit variance, but it will cause a problem when used together with smape loss, thus I tried switching to a clipped version MAE loss, which produced similar results compared to raw input with smape loss.

The model can be trained on CPU only machine in very short time.

I tried out some CNN, RNN models but couldn't get them working better than this simple model, and had to abandon them.

Training and validation setup

This is pretty tricky, and I am still not quite sure if I have done it correctly or not.

For approach 1 and 2

I tried to generate predictions for a few historical months, calculating daily smape scores locally. Then sample 25 days out to calculate a mean smape score. Do this sample-scoring a large number of times and take mean as local validation score. I used this score to select parameters.

For neural network

I split the history data into (X, y) pairs based on a splitting day, and then move the splitting day backward by 1 day to generate another (X, y) pair. Do this 60 times and vertically concatenate them to form my training data.

I used groupedCV split on the concatenated dataset to do cross-validation so that measures from one station don't end up in both training and validation set. During training, the batch size is specified so that data in the batch all based on the same splitting day. I did this trying to preventing information leaking.

I got average smape scores 0.40~44 for Beijing and 0.30-0.34 for London in my local validation setting. Which I think is pretty aligned with how it averages out through May.

Closing

Without utilizing any other weather information or integrating any sort of forecasts, all my models failed miserably for events like the sudden peak on May 27th in Beijing.

机器学习笔记 Week5 神经网络:学习

学习笔记(Machine Learning) Week5

全部笔记PDF版:http://vdisk.weibo.com/s/J4rRX/1373287206

Week5 神经网络:学习

神经网络:学习

1.1神经网络代价函数

首先引入一些便于稍后讨论的新标记方法:

  • L代表一个神经网络中的层数
  • Sl代表第l层的处理单元(包括偏见单元)的个数。
  • SL代表最后一层中处理单元的个数。
  • K代表我们希望分类的类的个数,与SL相等。

我们回顾逻辑回归问题中我们的代价函数为:

在逻辑回归中,我们只有一个输出变量,又称标量(scalar),也只有一个因变量y,但是在神经网络中,我们可以有很多输出变量,我们的hθ(x)是一个维度为K的向量,并且我们训练集中的因变量也是同样维度的一个向量,因此我们的代价函数会比逻辑回归更加复杂一些,为:

抓图12

这个看起来复杂很多的代价函数背后的思想还是一样的,我们希望通过代价函数来观察算法预测的结果与真实情况的误差有多大,唯一不同的是,对于每一行特征,我们都会给出K个预测,基本上我们可以利用循环,对每一行特征都预测K个不同结果,然后在利用循环在K个预测中选择可能性最高的一个,将其与y中的实际数据进行比较。

归一化的那一项只是排除了每一层θ0后,每一层的 Θ矩阵的和。最里层的循环j循环所有的行(由sl+1层的激活单元数决定),循环i则循环所有的列,由该层(sl层)的激活单元数所决定。

1.2反向传播算法(Backpropagation Algorithm

之前我们在计算神经网络预测结果的时候我们采用了一种正向传播方法,我们从第一层开始正向一层一层进行计算,直到最后一层的hθ(x)。

现在,为了计算代价函数的偏导数抓图13,我们需要采用一种反向传播算法,也就是首先计算最后一层的误差,然后再一层一层反向求出各层的误差,直到倒数第二层。

以一个例子来说明反向传播算法。

假设我们的训练集只有一个实例(x(1),y(1)),我们的神经网络是一个四层的神经网络,其中K=4,SL=4,L=4:

抓图14

我们从最后一层的误差开始计算,误差是激活单元的预测(daum_equation_1372579231428)与实际值(yk)之间的误差,(k=1:K)。我们用δ来表示误差,则:

daum_equation_1372579837430

我们利用这个误差值来计算前一层的误差:

daum_equation_1372580000259

其中g'(z(3))是S形函数的导数,g'(z(3))=a(3).*(1-a(3))。而(Θ(3))Tδ(4)则是权重导致的误差的和。

一下步是继续计算第二层的误差:

daum_equation_1372580797226

因为第一层是输入变量,不存在误差。我们有了所有的误差的表达式后,便可以计算代价函数的偏导数了,假设λ=0,即我们不做任何归一化处理时有:

daum_equation_1372581201202

重要的是清楚地知道上面式子中上下标的含义:

l代表目前所计算的是第几层
j代表目前计算层中的激活单元的下标,也将是下一层的第j个输入变量的下标。
i代表下一层中误差单元的下标,是受到权重矩阵中第i行影响的下一层中的误差单元的下标。

如果我们考虑归一化处理,并且我们的训练集是一个特征矩阵而非向量。在上面的特殊情况中,我们需要计算每一层的误差单元来计算代价函数的偏导数。在更为一般的情况中,我们同样需要计算每一层的误差单元,但是我们需要为整个训练集计算误差单元,此时的误差单元也是一个矩阵,我们用daum_equation_1372582015317来表示这个误差矩阵。第l层的第i个激活单元受到第j个参数影响而导致的误差。

我们的算法表示为:

daum_equation_1372582703224

即首先用正向传播方法计算出每一层的激活单元,利用训练集的结果与神经网络预测的结果求出最后一层的误差,然后利用该误差运用反向传播法计算出直至第二层的所有误差。

在求出了daum_equation_1372582015317之后,我们便可以计算代价函数的偏导数了,计算方法如下:

抓图15

在Octave中,如果我们要使用fminuc这样的优化算法来求解求出权重矩阵,我们需要将矩阵首先展开成为向量,在利用算法求出最优解后再重新转换回矩阵。

假设我们有三个权重矩阵,Theta1,Theta2和Theta3,尺寸分别为10*11,10*11和1*11

下面的代码可以实现这样的转换:

1.3梯度检验(Gradient Checking)

当我们对一个较为复杂的模型(例如神经网络)使用梯度下降算法时,可能会存在一些不容易察觉的错误,意味着,虽然代价看上去在不断减小,但最终的结果可能并不是最优解。

为了避免这样的问题,我们采取一种叫做梯度的数值检验(Numerical Gradient Checking)方法。这种方法的思想是通过估计梯度值来检验我们计算的导数值是否真的是我们要求的。

对梯度的估计采用的方法是在代价函数上沿着切线的方向选择离两个非常近的点然后计算两个点的平均值用以估计梯度。即对于某个特定的θ,我们计算出在θ-ε处和θ+ε的代价值(ε是一个非常小的值,通常选取0.001),然后求两个代价的平均,用以估计在θ处的代价值。

QQ截图20130630191648

Octave中代码如下:

当θ是一个向量时,我们则需要对偏导数进行检验。因为代价函数的偏导数检验只针对一个参数的改变进行检验,下面是一个只针对θ1进行检验的示例:

daum_equation_1372591667928

最后我们还需要对通过反向传播方法计算出的偏导数进行检验。

根据上面的算法,计算出的偏导数存储在矩阵daum_equation_1372591793607中。检验时,我们要将该矩阵展开成为向量,同时我们也将Θ矩阵展开为向量,我们针对每一个θ都计算一个近似的梯度值,将这些值存储于一个近似梯度矩阵中,最终将得出的这个矩阵同daum_equation_1372591793607进行比较。

QQ截图20130630193429

1.4随机初始化(Random Initialization)

任何优化算法都需要一些初始的参数。到目前为止我们都是初始所有参数为0,这样的初始方法对于逻辑回归来说是可行的,但是对于神经网络来说是不可行的。如果我们令所有的初始参数都为0,这将意味着我们第二层的所有激活单元都会有相同的值。同理,如果我们初始所有的参数都为一个非0的数,结果也是一样的。

我们通常初始参数为正负ε之间的随机值,假设我们要随机初始一个尺寸为10×11的参数矩阵,代码如下:

1.5综合起来

小结一下使用神经网络时的步骤:

网络结构:

第一件要做的事是选择网络结构,即决定选择多少层以及决定每层分别有多少个单元。

  • 第一层的单元数即我们训练集的特征数量。
  • 最后一层的单元数是我们训练集的结果的类的数量。
  • 如果隐藏层数大于1,确保每个隐藏层的单元个数相同,通常情况下隐藏层单元的个数越多越好。

我们真正要决定的是隐藏层的层数和每个中间层的单元数。

训练神经网络:

  1. 参数的随机初始化
  2. 利用正向传播方法计算所有的hθ(x)
  3. 编写计算代价函数J的代码
  4. 利用反向传播方法计算所有偏导数
  5. 利用数值检验方法检验这些偏导数
  6. 使用优化算法来最小化代价函数

课程地址:https://class.coursera.org/ml-003/class/index

机器学习笔记 Week4 神经网络:表达

学习笔记(Machine Learning) Week4

全部笔记PDF版:http://vdisk.weibo.com/s/J4rRX/1373287206

Week4 神经网络:表达

神经网络:表达

1.1非线性假设(Non-Linear Hypothesis)

之前我们已经看到过,使用非线性的多项式项能够帮助我们建立更好的分类模型。假设我们有非常多的特征,例如大于100个变量,我们希望用这100个特征来构建一个非线性的多项式模型,结果将是数量非常惊人的特征组合,即便我们只采用两两特征的组合(x1x2+x1x3+x1x4+...+x2x3+x2x4+...+x99x100),我们也会有接近5000个组合而成的特征。这对于一般的逻辑回归来说需要计算的特征太多了。

假设我们希望训练一个模型来识别视觉对象(例如识别一张图片上是否是一两汽车),我们怎样才能这么做呢?一种方法是我们利用很多汽车的图片和很多非汽车的图片,然后利用这写图片上一个个像素的值(饱和度或亮度)来作为特征。

假如我们只选用灰度图片,每个像素则只有一个值(而非RGB值),我们可以选取图片上的两个不同位置上的两个像素,然后训练一个逻辑回归算法利用这两个像素的值来判断图片上是否是汽车:

neural network

假使我们采用的都是50x50像素的小图片,并且我们将所有的像素视为特征,则会有2500个特征,如果我们要进一步将两两特征组合构成一个多项式模型,则会有约25002/2个(接近3百万个)特征。普通的逻辑回归模型,不能有效地处理这么多的特征,这时候我们需要神经网络。

1.2神经网络介绍

神经网络算法的来源:

神经网络算法源自对大脑的模仿。神经网络算法在八十到九十年代被广为使用过,再之后便逐渐减少了使用,但是最近又开始变得流行起来,原因是神经网络是非常依赖计算能力的算法,随着新计算机性能的提高,算法又成为了有效的技术。

神经网络算法的目的是发现一个能模仿人类大脑学习能力的算法。研究表明,如果我们将视觉信号传道给大脑中负责其他感觉的大脑皮层处,则那些大脑组织将能学会如何处理视觉信号。

sensors

下面是一个让舌头学会如何去看的例子。在一个盲人的头顶配置一台低像素的照相机,然后将照片的像素转换为不同的电极,每个像素都按照亮度给赋予一个不同的电压值。结果随着实验进行,这个盲人开始能够利用舌头看见眼前的东西。

blind people see

1.3模型表达

为了构建神经网络模型,我们需要首先思考大脑中的神经网络是怎样的?每一个神经元都可以被认为是一个处理单元/神经核(processing unit/ Nucleus),它含有许多输入/树突(input/Dendrite),并且有一个输出/轴突(output/Axon)。神经网络是大量神经元相互链接并通过电脉冲来交流的一个网络。

nuron

神经网络模型建立在很多神经元之上,每一个神经元又是一个个学习模型。这些神经元(也叫激活单元,activation unit)采纳一些特征作为输出,并且根据本身的模型提供一个输出。下图是一个以逻辑回归模型作为自身学习模型的神经元示例,在神经网络中,参数又可被成为权重(weight)。

neurons

1.4神经网络模型表达

神经网络模型是许多逻辑单元按照不同层级组织起来的网络,每一层的输出变量都是下一层的输入变量。下图为一个3层的神经网络,第一层成为输入层(Input Layer),最后一层称为输出层(Output Layer),中间一层成为隐藏层(Hidden Layers)。我们为每一层都增加一个偏倚单位(bias unit):

neural net work

下面引入一些标记法来帮助描述模型:

  • aij代表第j层的第i个激活单元。
  • theta代表从第j层映射到第j+1层时的权重的矩阵,例如theta1代表从第一层映射到第二层的权重的矩阵。其尺寸为:以第j层的激活单元数量为行数,以第j+1层的激活单元数为列数的矩阵。例如:上图所示的神经网络中theta1的尺寸为4*3。

对于上图所示的模型,激活单元和输出分别表达为:

activation unit and output

上面进行的讨论中只是将特征矩阵中的一行(一个训练实例)喂给了神经网络,我们需要将整个训练集都喂给我们的神经网络算法来学习模型。

1.5向量化实现(正向传播)Vectorized Implementation (Forward Propagation)

相对与使用循环来编码,利用向量化的方法会使得计算更为简便。以上面的神经网络为例,试着计算第二层的值:

222

我们令daum_equation_1372514573895,则daum_equation_1372514860191,计算后添加daum_equation_1372514962733

计算输出的值为:

333

我们令daum_equation_1372515089311,则daum_equation_1372515160729

这只是针对训练集中一个训练实例所进行的计算。如果我们要对整个训练集进行计算,我们需要将训练集特征矩阵进行转置,使得同一个实例的特征都在同一列里。即:

daum_equation_1372515388097

1.6对神经网络的理解

本质上将,神经网络能够通过学习得出其自身的一系列特征。在普通的逻辑回归中,我们被限制为使用数据中的原始特征x1,x2,...,xn,我们虽然可以使用一些二项式项来组合这些特征,但是我们仍然受到这些原始特征的限制。在神经网络中,原始特征只是输入层,在我们上面三层的神经网络例子中,第三层也就是输出层做出的预测利用的是第二层的特征,而非输入层中的原始特征,我们可以认为第二层中的特征是神经网络通过学习后自己得出的一系列用于预测输出变量的新特征。

1.7神经网络示例:二元逻辑运算符(Binary Logical Operators)

当输入特征为布尔值(0或1)时,我们可以用一个单一的激活层可以作为二元逻辑运算符,为了表示不同的运算符,我们之需要选择不同的权重即可。

下图的神经元(三个权重分别为-30,20,20)可以被视为作用同于逻辑(AND):

and

下图的神经元(三个权重分别为-10,20,20)可以被视为作用等同于逻辑(OR):

229

下图的神经元(两个权重分别为10,-20)可以被视为作用等同于逻辑(NOT):

or

我们可以利用神经元来组合成更为复杂的神经网络以实现更复杂的运算。例如我们要实现XNOR功能(输入的两个值必须一样,均为1或均为0),即XNOR=(x1ANDx2)OR((NOTx1)AND(NOTx2))

首先构造一个能表达(NOTx1)AND(NOTx2)部分的神经元:

230

然后将表示AND的神经元和表示(NOTx1)AND(NOTx2)的神经元以及表示OR的神经元进行组合:

231

我们就得到了一个能实现XNOR运算符功能的神经网络。

1.8多类分类

如果我们要训练一个神经网络算法来识别路人、汽车、摩托车和卡车,在输出层我们应该有4个值。例如,第一个值为1或0用于预测是否是行人,第二个值用于判断是否为汽车。

下面是该神经网络的可能结构示例:

232

神经网络算法的输出结果为四种可能情形之一:

daum_equation_1372517792858

课程地址:https://class.coursera.org/ml-003/class/index