2022

距离上一次整理博客已经有一年的时间。归国,工作,换岗和疫情似乎把间隔的时间缩的很短,仿佛就是一瞬间。

春末

我似乎已经记不清年初的琐碎之事,大约在四月初,终于下定决心改变。从数据转向了项目会是今年工作上的一大转变吧。毕竟面向许多未知,趁此闲暇之时赴了一趟苏州。很喜欢慢的生活。绿植,白墙,黑瓦会给我一种特别干净但又充满生机的感觉。

摄于同里 2021.04.21

盛夏

今年夏季似乎特别长,持续到了好几个月。由于疫情的关系,蜷缩在空调房里开着视频电话会议,阅读着技术文档和密密麻麻的代码块。购置了一台现在又近乎吃灰的制冰器,妄想着可以靠它制作的冰咖啡支棱起每个我每个困意满满的下午,而后发现冰箱还是更方便。也罢,但至少习惯上了每个下午给自己来上一杯冰拿铁,完全属于自己的休闲时光。大约就是一整个夏季了

摄于桂林 2021.09.18

凉秋

广州的秋天估摸一周,美好又短暂。今年破例吃了人生第一次吃的星巴克月饼,发现味道其实很一般,没有大班的细腻。但要说中秋最喜欢的食物,还是紫苏叶炒田螺。

摄于2021.09.13 生日礼物

暖冬

终于来到最喜欢的冬天。避开酷热的夏天,放弃了可望不可及的秋天,有阳光的冬天是最舒服的时间。冬天似乎是一切的结束,又是一切的开端。很多计划制定,年终感谢祭都被安排了在这一小段时间。

摄于2021.11.27 拍摄现场

尝试了一次架子鼓的演出,时间略显仓促最终也没有获得很满意的效果,但似乎在即时播放的时候大家更多被音乐本身的美好感染。似乎大家在这个寒凉的季节都会变得越发热情和关怀,内心充满平静和感恩。

距离我完成这一篇流水账,应该是还有两小时便跨入新的一年。在2021最后的这一小段时间,坐在屏幕前听着音乐,敲着自己的过往,感觉就像把一年以来收获的种种事物包装分类归纳放置好,有着莫名的满足感。也或许夹杂了我找回了之前码字的欣慰吧。循例祝愿自己和身边的人新的一年顺顺利利

Bonne Année

2018

当开始准备写今年第一篇日志时,翻到去年日志看到开篇提及的在欢乐的聚餐和斗地主中渡过,不禁感慨今年亦是如此相似,只是地点从南特去到了巴黎。或许耐寒基因不好,并没有在寒冷的冬天挤在人潮涌涌的香舍丽舍大街看倒数和烟花。我忽然发现记录下一些很有趣的片段并不断回味也是一件趣事,哪怕只有自己看,或者与自己至亲分享,总觉得无比快乐。

去天台喝杯咖啡

去年冬天回了一趟国并不能赶上春节,匆匆忙忙在三月份又返回法国,因为我开始在这边的一份六个月的长实习。入职当天天气还是很冷,披着风衣顶着小雨一路到了公司办完一切手续。中午跟同事们午餐并尬聊着,发现其实一切适应并没有想象中的难。

有时午饭以后,总是会跟着同事们去天台喝杯咖啡,聊天或者嗮太阳,直到下午开工。咖啡似乎在开始工作之后一直伴随着我。

春天花儿开

一旦开始上班,假期就是一个奢侈的词。实习生没有年假,幸好有很多一日的假期在星期一或者星期五,这样我能有一个长周末。四月份的天气已经慢慢转暖,趁着小假去了一趟南特附近的小镇Clisson。欧洲城市一个样,乡村更显的有人情味,加之绿树城堡和鲜花更有万物生机的感觉。

横穿大西洋

并不是每一个假期都会出去,有的时候懒癌发作哪怕是稍长一点的假期也宁愿懒散地躺在床上晒太阳,直到夏天即将到来觉得再不出去就会发霉了。在一个风和日丽阳光普照的日子,我和同学们一起去海边骑行。依稀记得上一次环绕安纳西湖骑行40公里只是一个上午的事情,因此天真的认为58公里的路途并不艰难。

摄于骑行去Ile de Yue 海上公路 2017.07.15

然而事实证明我们的想法太天真。猛烈的紫外线,笨重的单车,崎岖的道路让我们在最后十公里的路程几乎五分钟歇一次脚。当时我就觉得或许今年都不会再骑单车了,结果还真的是。即便很疲惫,回想起趁着海浪褪去骑在露出的道路上还是很奇妙的感觉。

告一段落

九月份除了是生日的月份,毕业的月份,还是一个踏上求职的月份。在答辩完收齐老师的评分卷,合上笔记本电脑,关上视频摄像头,我终于如释重负。我还清楚地记得企业导师和学校老师关心地询问我未来的想法,并认真的跟我说恭喜毕业,心情是高兴又失落。其实每逢一段转折,告一段落的节点处我总是会有这种感觉,强烈又短暂,很快便被我赶去火车站的仓促感替代。

摄于法国毕业礼场馆外 2017.10.14

毕业礼最开心的莫过于亲近的人都在身边。

神圣又不美丽

希腊对于我一直都是一个充满神秘的地方,帕特农神庙和雅典卫城的那些宏伟的断壁残垣一直隔着一本书的距离,直到自己亲眼目睹。在抵达神庙时感受到的是旅游胜地的人潮涌涌和聒噪的谈话声,竟然少了印象中的宏伟壮阔。

也许是经济衰败的原因,公共交通的服务公职人员冷漠的态度,繁忙时段的十分钟一趟的地铁,市中心一公里以外脏乱差的街区公路,似乎在拉低这座具有辉煌古文明的城市素质。或许雅典这里是我必定会选择去一次而不会再度重游却也念念不忘的欧洲城市。

熟悉的冬天

十一月回到了广州,忽然想起已经有两年未曾在广州度过这段忽冷忽热的季节,偶尔穿着短袖挤地铁,偶尔穿着大衣去咖啡厅避寒,这就是熟悉的冬天。

阳光还是家乡

在回国的飞机上无意中瞥见星座运势,虽然不怎么相信这些玄学,但面临选择这四个字我却记得清清楚楚。尼斯实验室的工作终究觉得太遥远,广州亲切的感觉终究还是无法抗拒。其实选择不仅是一个理性的过程,也是一个感性的过程,我也不清楚为什么执着于回到原点,或许原点更适合作起点吧。

圣诞在等我

十二月二十六日早上抵达巴黎,第二天晚上路过Place de Chatelet,惊喜地发现圣诞集市还没有收,熟悉的烤串和热红酒,也许是今年,也是明年最后一次品尝了。

期盼

当我在罗列着小标题的时候,我才发现自己原本以为非常单调的生活,还是夹杂着很多小趣事。转眼间就开始新的一年,开始工作的第一年一定要要好好加油,也祝愿自己,亲人和朋友都能顺顺利利地度过新的一年。

Cross-entropy

代价函数,或者称为损失函数(loss function)用于衡量系统输出和期望输出的误差大小,通过向着逐步减小代价函数的方向,也就是函数关于参数的梯度的负方向调整参数,我们就减小误差,从而优化模型。一般情况下我们会使用均方差(MSE:Mean Square Error)作为代价函数,因为均方差有很好的几何解释,可以视为欧几里得空间的距离。然而在神经网络中,我们会使用交叉熵(Cross-entropy)作为代价函数而不使用我们常用的均方差,原因在于神经网络中有一个特殊的部分:\sigma激活函数(\sigma(z) = \sigma(wx+b), z = wx+b)。实践证明如果使用均方差作为代价函数,在误差大的时候学习得不快,这个与我们的直觉相悖。我们应该认为,误差越大越应该更快地朝优化的方向前进。造成这种现象的原因解释如下:

设代价函数 C = \cfrac{(y-a)^2}{2} , 其中a = \sigma(z) = \sigma(wx+b) 。学习得不快可以理解为下降的都不大,也就是函数的梯度值不大。现在求一下C 关于w 的偏导数,也就是关于w的梯度。根据链式法则有:

\cfrac{\partial C}{\partial w} = \cfrac{\partial C}{\partial a} \cfrac{\partial a}{\partial w} \\ = (a-y) \cfrac{\partial \sigma(wx+b)}{\partial w} \\ = (a-y) a^\prime

由此可以看出,下降速度除了和预测与真实值之间的差值有关以外,还乘了一个倍率。这个倍率是\sigma(wx+b) 函数的导数。而由\sigma(z)函数图像(如下)可知显然在两端倒数几乎为0,只有在中间部分才很大。这就是问题的根源。

交叉熵解决这个问题的方式就是构造出一个新的代价函数C^\prime, 使得\cfrac{\partial C^\prime}{\partial w} 的表达式a^\prime = \cfrac{\partial \sigma(wx+b)}{\partial w} 这一项,也就是不含$sigmoid$ 的导数。构造出来的代价函数为C^\prime = y\ln a + (1-y)\ln {(1-a)} 。 对C^\prime 求偏导数:

\cfrac{\partial C^\prime}{\partial w} = (\cfrac{y}{a} + (-\cfrac{1-y}{1-a})) (\cfrac{\partial \sigma(wx+b)}{\partial w}) \\ = (\cfrac{y}{a} -\cfrac{1-y}{1-a}) a^\prime

又因为$sigmoid$ 函数的特殊性,我们可以用它本身来表示它的倒数,也就是a^\prime = a (1-a) , 代入上式可得: 

(\cfrac{y}{a} - \cfrac{1-y}{1-a}) a(1-a) = \cfrac{y(1-a) - a(1-y)}{a(1-a)} a(1-a) \\ = y-ay -a + ay \\ = y - a

也就是我们获得了\cfrac{\partial C^\prime}{\partial w} = y-a 的梯度。这个梯度和\sigma(z) 的导数毫无关系,而且模型预测和真实输出的差值越大,梯度就越大,梯度下降的速率就越大,学习就越快。这就是为什么神经网络需要使用交叉熵的代价函数而不是均方差代价函数了。

附:简单证明a^\prime = a (1-a)

\cfrac{d}{dx} \sigma(x) = \cfrac{d}{dx} \left[ \cfrac{1}{1 + e^{-x}} \right] \\ = \cfrac{d}{dx} \left( 1 + \mathrm{e}^{-x} \right)^{-1} \\ = -(1 + e^{-x})^{-2}(-e^{-x}) \\ = \cfrac{e^{-x}}{\left(1 + e^{-x}\right)^2} \\ = \cfrac{1}{1 + e^{-x}\ } \cdot \cfrac{e^{-x}}{1 + e^{-x}} \\ = \cfrac{1}{1 + e^{-x}\ } \cdot \cfrac{(1 + e^{-x}) - 1}{1 + e^{-x}} \\ = \cfrac{1}{1 + e^{-x}\ } \cdot \left( 1 - \cfrac{1}{1 + e^{-x}} \right) \\ = \sigma(x) \cdot (1 - \sigma(x))

Sorting Algorithm

选择排序

排序思想:每次挑选最值(最大值或者最小值)然后顺序放在前面(或者后面)以达到升序(或者降序)的排序。以升序为例,从第一个开始挑选最小的放在第一位,然后再从除了第一个之后的所有元素挑选最小的,放在第二位,以此类推。

复杂度解释:显然从第一个开始挑选到最后一次挑选需要一个循环,每次挑选过程都要遍历剩下的元素,因此内嵌一个循环。算法复杂度时O(n^2)

template<class T>
void select_sort(std::vector<T> &v){
    for (int i = 0; i<v.size(); i++) {
        int min_index = i;
        for (int j = 0; j<v.size(); j++) {
            if (v[min_index]<v[j]) {
                std::swap(v[min_index], v[j]);
            }
        }
    }
}

冒泡排序

排序思想:大的元素不断上升或者小的元素不断沉底。“不断”的过程可以用两个循环来实现。两两比较如果满足条件就交换。

template<class T>
void bubble_sort(std::vector<T> &v){
    for (int i = 0; i<v.size(); i++) {
        for (int j = i; j<v.size()-i-1; j++) {
            if (v[j+1]<v[j]) {  //if next one is smaller then swap
                std::swap(v[j], v[j+1]);
            }
        }
    }
}

插入排序

排序的思想:类似于扑克牌的整理,依次挑选并与之前的比较,插入到合适的位置。由于插入到之前的位置需要把该元素之前的部分元素依次后移,所以需要一个while循环来进行迭代赋值。然后最后再把要插入的元素的值覆盖到所在的位置。
注意,因为要表示下一个元素,用到i+1,所以循环要改成v.size()-1以保证不越界。同时为了避免空数组的v.size()-1<0的情况发生,还需要一个简单的if判断。

template <class T>
void insert_sort(std::vector<T> &v) {
    if (v.size() > 1) {
        for (int i = 0; i<v.size()-1; i++) {
            T next_value = v[i+1];
            int next = i+1;
            while(v[next-1] > next_value ){ //if next one is smaller than previous
                v[next] = v[next-1]; //overwrite the next one with privous
                next--;
            }
            v[next] = next_value;
        }
    }
}

快速排序

排序思想:不断划分小块。如果在升序的情况,则划分点左边的元素值均小于划分点的值,划分点右边的值均大于划分点的值。可以先选择最后一个元素作为划分点,然后陆续遍历一次把前面所有元素和划分点比较,设置一个用来记录比划分点小的index,当遇到比划分点小的值时用来交换。遍历结束后把划分点移动到index的前面,这样就保证了左边小于划分点,右边大于划分点。一次partition的过程可以用下图说明:

template <class T>
int partition(std::vector<T> &v, int first, int last){
    T pivot = v[last];
    int i = first - 1;
    for (int j = first; j<v.size()-1; j++) {
        if (v[j]<pivot) { //如果当前值小于pivot的值
            i++; 
            std::swap(v[i], v[j]);
        }
    }
    std::swap(v[i+1], v[last]); //最后把pivot指的元素放在最后一个比它小的元素的前面
    return (i+1);
}

template <class T>
void quick_sort(std::vector<T> &v, int first, int last) {
    if (first<last) {
        int pi = partition(v, first, last);
        quick_sort(v, first, pi-1); 
        quick_sort(v, pi+1, last); 
    }
}

归并排序

排序思想:最后一种常用的排序是归并排序,其代码会稍长,但思路是比较容易理解的。
首先主函数每次迭代都需要计算一个新的中点,就是为了不断切分成小块,迭代地调用自身,并传入左半部分和右半部分进去。与快排不一样,快排是在分块的时候排序,而归并是在合并的时候排序,因此merge函数是在两个自身递归调用的下面。merge函数内容分为以下几个步骤:

  1. 创建两个vector,分别存放左半部分[first, middle-first+1]和右半部分 [middle, last-middle]
  2. 依次把原数组的firstmiddle-first+1的元素复制到左半部分
  3. 依次把原数组的middlelast-middle的元素复制到右半部分
  4. i指向左半部分第0个,j指向右半部分第0个,当ij都不超过各自数组时,k指向原数组要被覆盖的第0个,也就是k=first。循环比较把小的重新覆盖到原数组去
  5. 然后再用while循环把剩下的复制到原数组去
  6. 结束
template <class T>
void merge(std::vector<T> &v, int first, int middle, int last) {
    int i, j, k;
    int n1 = middle-first+1;
    int n2 = last - middle;
    std::vector<T> v1(n1);
    std::vector<T> v2(n2);
    
    for (i = 0; i< n1; i++)
        v1[i] = v[first + i];
    
    for (j = 0; j<n2; j++)
        v2[j] = v[middle+1+j];
    
    i = 0;
    j = 0;
    k = first;
    
    while (i<n1 && j < n2) {
        if (v1[i]<v2[j]){
            v[k] = v1[i];
            i++;
        }
        else {
            v[k] = v2[j];
            j++;
        }
        k++;
    }
    
    while(i<n1){
        v[k] = v1[i];
        i++;
        k++;
    }
    
    while(j<n2){
        v[k] = v2[j];
        j++;
        k++;
    }
}

template <class T>
void merge_sort(std::vector<T> &v, int first, int last){
    if (first < last) {
        int middle = first + (last - first)/2;
        merge_sort(v, first, middle);
        merge_sort(v, middle+1, last);
        merge(v,first, middle, last);
    }
}

计数排序

排序思想: 通过一个计数的数组来存放各个元素应该在的位置,然后在重新拷贝到结果数组去。这里需要获得一个最大值。比如要排序[1 4 1 2 7 5 2],则需要知道最大值是7,这样才可以创建一个有7个元素的计数数组。弊端是空间的损失,如果最大值很大,则要创建的计数数组也很大。

template <class T>
void count_sort(std::vector<T> &v, int max) {
    
    //create a count vector
    std::vector<int> count(max+1);
    for (int i = 0; i < v.size(); i++) {
        count.at(v[i]) ++;
    }
    
    //self increment of count vector
    for (int i = 1; i < count.size(); i++) {
        count[i] += count[i-1];
    }
    //create result vector
    std::vector<int> result(v.size());
    
    //put the element in the correct position in result vector
    for (int i = 0; i<v.size(); i++) {
        int current_index = count[v[i]]-1;
        result[current_index] = v[i];
        count[v[i]] --;
    }
    
    //copy the result to the input vector
    v=result;
}

堆排序

堆排序中,因为二叉堆是一个完全二叉树,因此我们可以使用数组的形式来表示二叉堆。否则就要用一些符号来填充数组某些位置以表示空节点。
数组表示的二叉堆,设双亲位置为ii从0开始
则左孩子的位置为2*i + 1
且右孩子的位置为2*i + 2
最大堆就是双亲>左右孩子最小堆就是双亲< 左右孩子
升序排序用最大堆,降序排序用最小堆。

def heapify(arr, n, i):
    # 先把parent设为最大的,parent的位置为i
    largest = i  
    # 然后根据公式 写出左右child 的位置 2i+1, 2i+2
    l = 2 * i + 1     
    r = 2 * i + 2     
 
    # 如果左孩子存在,也就是l< n 且左孩子的值比largest的位置的值大
    # 则设最大值的位置为左孩子的位置
    if l < n and arr[largest] < arr[l]:
        largest = l
     
    # 同理判断右孩子存在与否 并和largest位置的值比较
    if r < n and arr[largest] < arr[r]:
        largest = r
 
    # 如果largest的位置和parent的位置不一样,证明最大值不在parent那里
    # 则将largest位置的元素和parent位置的元素交换
    # 并且继续递归调用
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]  # swap
        heapify(arr, n, largest)
        
def heap_sort(arr):
    n = len(arr)
 
    # 对于数组表示的二叉堆,能作为parent的只有前 n//2 -1 个元素
    # 应该从最下面的parent开始进行最大堆化,
    # 这样才能保证循环完整个二叉堆都是最大堆
    # 可以由不等式的方式说明
    for i in range(n//2-1, -1, -1): 
        heapify(arr, n, i)
    
    # 建立完二叉堆之后就是顺序取出二叉堆的元素即可得到有序数组
    # 方法把第一个放到最后,然后固定最后的再把前面的最大堆化
    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]   
        heapify(arr, i, 0)

Support Vector Machine

关于SVM的笔记,因为涉及多次对偶问题以及线性规划问题的求解,故记录下公式公式推导过程,以便对SVM的基本原理有更进一步的了解。

样本点的表示

设有m个样本点 D = \lbrace(X_1,y_1) ,(X_2,y_2)...(X_m,y_m) \rbrace
其中每个样本点为 dX_i = (x_1, x_2...x_d)
每个样本的标签取值为 y_i = \pm 1+1 表示属于该标签,-1表示不属于

超平面的表示

设存在d维的超平面:w_1x_1+w_2x_2 + ... w_dx_d + b = 0
W = (w_1,w_2 ... w_d)
超平面方程可以写成:

W^TX + b = 0

(1.1)

W为超平面的法向量,b为超平面的位移。
特殊地,当d=2时超平面是一条直线: w_1x_1 + w_2x_2 + b = 0 斜率-\cfrac{w_1}{w_2},截距-\cfrac{b}{w_2}

正确分类的表示

如果一个样本(X_i, y_i)正确分类,则必有:

\begin{cases} W^TX_i+b \ge + 1 ,y_i= + 1 \\ W^TX_i+b \le - 1 ,y_i= - 1\end{cases}

(1.4)

也就是如果超平面能正确分类样本点,则当样本点Y_i = +1时,代入X_i到超平面方程后得到的值是大于 +1 的,反之当样本点Y_i = -1时,代入X_i到超平面方程后得到的值是小于 -1 的。注意到Y_i的取值仅仅是符号的作用,所以可以把式(1.4)简化为:

y_i (W^TX_i+b) \ge 1

(1.5)

样本点到超平面的距离

一个点 X =(x_1, x_2, ..., x_d)到超平面的距离可表示为

d = \cfrac{\vert w_1x_1+w_2x_2 + ...w_dx_d + b \vert}{\sqrt{w_1^2+w_2^2 + ... w_d^2}}

(1.2)

用矩阵的形式表示W和X,同时用 \Vert w \Vert 表示 \sqrt{w_1^2+w_2^2 + .. w_d^2} , 则式(1.2) 可以写成:

d = \cfrac{\vert W^TX \vert}{\Vert w \Vert}

(1.3)

目标函数的确立

当样本集严格线性可分时,存在不止一种Wb的组合满足上式。因此必须找出最优的超平面来分割。设y_i = +1 的样本为正样本,y_i = -1 的样本为负样本, 则最优的定义就是离超平面最近的正样本和负样本的距离都最大。设间隔为离超平面最近的正样本和负样本的距离之和,则目标就是找出一组Wb使得间隔的值最大。


设经过最近正样本的超平面为W^TX+b=1 也即W^TX+b-1=0, 经过最近负样本的超平面为W^TX+b +1 = 0 。由于W相等故两直线平行,间隔为两平行线的距离:

d = \cfrac{\vert (b-1) - (b+1) \vert}{\Vert w \Vert} = \cfrac{2}{\Vert w \Vert}

(1.6)

由于最大化\cfrac{2}{\Vert w \Vert}比较难计算,因此转化成最小化\cfrac{1}{2}\Vert w \Vert^2

因为我们要在正确分类的前提下求间隔的最大值,也就是结合式(1.5)和(1.6)转化成一个在一定约束条件下的规划问题(1.7)。

\begin{cases} \min\limits_{W, b} \cfrac{1}{2}\Vert w \Vert^2 \\ \text{subject to: } y_i (W^TX_i+b)\ge 1 , i = 1,2,3...m \end{cases}

(1.7)

整合约束和目标函数

在特定约束下求最值时麻烦的,因为不能直接求目标函数最值,然后再去比较是否符合约束。最简单的方式就是引入拉格朗日算子将目标函数和约束整合在一起。设\alpha是拉格朗日算子。
因为y_i (W^TX_i+b) \ge 1 可写成 1-y_i (W^TX_i+b) \le 0,则有

\min \limits_{W, b} L(W, b, \alpha) = \cfrac{1}{2}\Vert w \Vert^2 +\sum_{i=1}^{m}\alpha_i(1-y_i (W^TX_i+b))

(1.8)

原问题转化为一个对L(W, b, \alpha)的最大最小值问题。也就是:

\min \limits_{W, b} (\max\limits_{\alpha}L(W, b, \alpha))

(1.9)

由于先求\alpha的最值较为困难,所以再转化为

\max \limits_{\alpha} (\min\limits_{W, b}L(W, b, \alpha))

(1.10)

对式(1.10)的W, b求偏导数得到:

W = \sum_{i = 1}^{m} \alpha_ix_iy_i

0 = \sum_{i = 1}^{m} \alpha_iy_i

(1.11)

(1.12)

将式(1.11)和(1.12)代回(1.10)可得到仅关于\alpha的函数(1.13):

\max \limits_{\alpha} \sum_{i = 1}^{m} \alpha_i - \cfrac{1}{2}\sum_{i = 1}^{m}\sum_{j = 1}^{m} \alpha_i\alpha_jy_iy_jx_i^Tx_j

\text{subject to:} \sum_{i = 1}^{m} \alpha_iy_i = 0a_i \ge 0

(1.13)

根据KTT采用SMO算法解出alpha然后确定Wb。由于超平面是由Wb确定,因此超平面确定,至此模型训练完成。

从线性可分到不完全线性可分

为了使某些样本可以不满足约束y_i (W^TX_i+b)\ge 1, 引入松弛变量C。于是式(1.8)可以改写成

\min \limits_{W, b} L(W, b, \alpha) = \cfrac{1}{2}\Vert w \Vert^2 + C*\sum_{i=1}^{m}loss((1-y_i (W^TX_i+b)))

(1.8)

其中loss()函数可以有以下选择:

  • 0/1损失函数:loss(z) =\begin{cases} 1, if z < 0 \\ 0, otherwise \end{cases}
  • hinge损失函数:loss(z) = \max (0, 1-z)
  • 指数损失函数: loss(z) = \exp(-z)
  • 对率损失函数: loss(z) = \log(1+\exp(-z))

2017

还是一句老土的开场白,转眼间2016就过去了。在聚餐和欢乐的斗地主游戏中与新的一年相会,在车里弹着吉他回到宿舍就寝。在迎接新的一年之前,我希望记下一些过去的关键片段,避免自己遗忘了美好,毕竟那些经历和记忆才是一年里最宝贵的最真心的东西。

认知

我不希望记下流水账,毕竟流水账可以从我各种社交网络找回。或者说单纯性的记事并不能包含更多有意义的内容。我希望记下与事情相关的认知,这些认知可能往后会发生改变,但它们毕竟是我这段时间内所经历和所思所想的。

昼长夜短

从2015年的冷冬跨过迎来2016年的春天甚至夏天的期间,是煎熬和期待的时期。那个时候一方面因学业和实习的压力而稍有疲惫,另一方面因短暂的冬天和过早的商店停业而烦恼。我才开始认真观察手机里的日出日落时间,随着白天的时间慢慢加长,心境竟然慢慢变好,真是很神奇。

恐袭危机

2015年过得并不太平,2016也未曾好过。就在巴黎恐袭后长长的一段时间关注度从到处搜罗网站信息到时不时看一下新闻日报,但夏天却迎来了尼斯事件和德国枪击,还有土耳其军事政变。故事仍在继续,圣诞假期又爆发了瑞士德国和土耳其的恐袭消息。难道欧洲已经成为了正如有些学者所说的年久失修的巨轮,还是这一直以来存在着的问题直到现在才引发我自己的关注呢?

中欧国家

年末一趟旅游让我稍微擦觉到东欧国家与西欧的不同。无论是建筑风格上更为保守甚至乎有俄的影子外,缺少了西欧的一种精致感。其次是菜肴,并没有凸显极具特色的美食,反倒受法德的影响很深。开车让路和市内高车速会导致更低的安全感。总体感觉难民更少。 

户外活动

越来越觉得带有景色的旅游比简单游历城市和逛商场购物来的更有趣。越来越觉得摄影也算是一种户外活动,或者说是户外活动的唯一目的,比如一遇见下雪就出门外拍。从旅游是为了拍照过渡成拍照是为了旅游。除了打球跑步,甚至爱上骑行,徒步,攀爬等简单却磨练意志的有趣活动。这种感受比起单纯的锻炼或者单纯的旅拍来得更刺激而难忘。

选择取舍

在本科入硕士面临的选择中取了计算机,如今在计算机众多方面中寻找兴趣点仍然是自己在努力的事情。易上手的只是表象,能无惧疲惫做下去的才是自己的喜爱。趁着时间尚有可以尝试多个方面,毕竟之后的路也很长。寻找的同时也要有专一性,毕竟毕业不遥远。

音乐素养

这种自从我开始学钢琴以来就认为很虚的东西在抵达法国以及游历中欧各地区后感觉越发强烈。法国的火车站和机场有钢琴以及乐意演奏的候车客,地铁有交响乐团。节日有管弦乐团在圣诞集市表演。人们围观而鼓掌。会安静地听音乐会并且神情自然而享受。灯光秀的动听配乐和安静观看的上百个安静的市民观众。这些点滴和侧面总会让你感觉到音乐的重量,模糊掉音乐本身和生活本身的界限。

生活

我也想从一些客观的小事物反映自己去年的生活状况和感受。虽然生活中充斥着许多事物,我愿意挑出一些相比于以往接触更多的。毕竟是它们让我的生活变得更2016。

咖啡

咖啡似乎在我的2016年扮演着重要的地位。以前不明白和抗拒Expresso是因为其苦味浓厚和分量小,然而现在却渐渐爱上了这东西。在这里的咖啡机无论是宿舍楼下的宿舍贩卖机,街道上的cafe & bar和面包店都可以买到一杯热腾腾的Expresso。我会在餐后,休息时,聊天,避雨,工作,招待朋友,听音乐,手脚冰冷等短暂时刻来上一杯。有的时候甚至要一杯double Expresso才能满足我品味它的时长。

代码

与其所代码不如说它们只是构成我生活另外一部分很重要的元素。本身并无很强计算机基础的我开始接触不同的语言,编写各式各样的代码,感受不同的风格带来的便捷性。终究发现出一些编程语言间的共通性,然后开始逐渐回归算法的学习。

法语

法语逐渐成为了一部分生活的重心,一方面在于日常交流所需,另一方面发现这种语言的魅力并不再在于发音有多好听(或许很多人觉得小舌音根本不好听),而是在于它描述和表达所用的单词。在这一年的熏陶下我甚至会出到非法语地区有稍许怀念起法语,或者是在机场与法国人聊天找到一点巧妙的亲切感。

足迹

足迹是为了清楚我一年内生活或游历过的地方。我发现一些早期去的城市名字逐渐模糊甚至忘记如何拼写。但当寻获并默念起那个城市的名字,脑海中会浮现起当时所发生的人和事物。在2016年除开广州和南特,我一共在23个城市停留过,我决定趁着记忆尚未模糊记下我对这些城市和我当时的活动的记忆。当然如果这些简短的文字能成为以后计划旅行的参考,也算是它们存在的另一种价值吧。

巴黎

2016年算上来回机场的话一共去了5次巴黎。即便在前年亦专程游玩过一次。但每一次去巴黎都有不同的感受。最初是独自前往会见亲戚,租了一个市中心的房间住了五个晚上。房东是一个法国老人,每天上午早安后可以吃到新鲜的面包和咖啡。第二次是与Pauline等朋友们游玩迪士尼,印象最深刻的就是来回搭乘过夜 Euroline 来回巴黎。第三次是送机,由于时间关系在巴黎住了一晚,去了一直以为‘很危险’的蒙马特高地,发现不过是有许多黑人拦截在路边要卖。平心而论,登顶蒙马特高地俯视小巴黎全景的感觉很赞,似乎一瞬间囊括了所以巴黎精致的建筑和剪影。

波尔多

波尔多的旅游是由ESN组织的。乘坐大巴从南特往返波尔多并不是非常远。在波尔多参观了主要的几个教堂建筑和镜面广场,波尔多市中心的商街却是比南特的更大。小惊喜是喝到了不正宗却不差的奶茶。波尔多旅游的时间是春天,而我的城市旅游通常会囊括逛公园。一方面公园给人一种安静舒服的感觉,另一方面每个城市的每座公园都有自己特色。在第二天的行程我去了波尔多的植物园,到现在我都记得当时的蓝天和树上的花:

昂热

昂热是距离南特一个小城市,一直以来对昂热的印象都是去巴黎半小时后第一个抵达的中停站。终于在暑假的一个周末抽了一天前往昂热游玩。城堡最具特色的是围墙上的步道,石头面是附着的藤蔓和花朵,步道望下去种植在屋顶的葡萄和蔬菜,城堡内的花园和树藤拱门以及上下步道两侧的绿树成荫,正是这种充满生机活力的植物让古老的城堡有一丝生机和活力。

雷恩

精确来说是雷恩和圣米歇尔山。由于无法直达圣米歇尔,雷恩是一个小驿站。圣米歇尔山算是法国除了铁塔,另一个更富有历史感的地标型建筑。准确来说是一个浅滩小高地上的城堡和修道院。夏天水涨使得高地变成岛,冬天潮退露出泥水和植物。雷恩距离圣米歇尔并不遥远,却也是一座现代化城市,这里的精髓不在于有许多声名远扬的建筑群,而是在于它所记载所有布列塔尼的历史。

马赛

马赛是暑期实习后前往度假的一个城市。一直以来都想一睹南法风貌,在6小时的TGV后我拎着行李箱穿梭在混杂的人群中上了地铁。我并没有仔细的逛马赛市区,这或许是一个遗憾,但也是因为当时就在离马赛不远的尼斯发生了事故。即便如此,马赛峡湾和日光浴是我对南法的全部印象。

安纳西

安纳西是临近瑞士日内瓦的一个美丽的法国旅游城市。城市不大但却吸引着成千上万游客前往,其原因想必是安纳西城区里有趣的步行街。这里的步行街两侧都有很多饰品店和餐厅,步道是在一个拱门下面,有点像广州的骑楼,却没有骑楼那么高大。整个步行街区域的建筑和路都是石头砌成的,两侧还有河流和花草。中心地带有一个位于河中间的岛宫,它便是安纳西的标志。除开商业区,安纳西湖也是一个美丽的地方,在这里我和朋友们完成了4小时环湖的骑行,如果非赶时间,沿途的风景足够我们游玩一天。

戈尔德

戈尔德是一日往返的石头城,不知何时已成为热门的旅游景点。戈尔德的石头城是一个饶有趣味的地方,在这里你可以体验在石头砌的各种小道和楼梯间穿梭,有时从黑暗的巷子里走出来便是一个可以遥望众山的平台。戈尔德也是一个徒步的好去处,从这里可以徒步前往红土城和修道院。4公里徒步距离的修道院成为了我们最终的选择,这里徒步的乐趣在山里碎石铺好的路和树林间穿行。

舍农索

由南特学生联合会组织的一次小出游,参观舍农索城堡。卢瓦河谷地带的城堡群真的是一道风景线,除了南特的布列塔尼城堡和昂热城堡以外,舍农索城堡算是我们参观的第三个大城堡。时间正值秋天,泛黄的树叶和清澈的蓝天衬托的城堡更为美丽。

拉罗谢尔

拉罗谢尔海滨城市算是第二次到来了。这次来拉罗谢尔正值万圣节假期,我因为刚刚回法国安顿一切并没有强烈旅游的意愿,便选择拉罗谢尔放松心情。这次我们走到了拉罗谢尔城堡另一侧的沙滩,正好赶上日落时分。哈,耀眼的阳光我眼睛都睁不开了呢。

圣纳泽尔

传说中的圣村就是圣纳泽尔,我们学校另外一个分部的所在地,直到2016年10月才算真正来到。想起第一次来圣纳泽尔就是‘开学典礼’。 那个时候刚来法国不久,面对陌生景色的激动和兴奋,跑到海边拍照甚至忘记上车。第二次来圣纳泽尔是拜会做项目的公司,一个下午就来回圣纳泽尔,对真正的容貌了解还是留到了这次旅程。我为了去圣纳泽尔度假,并没有参加毕业晚会,一方面我觉得我们专业并没有认识的人毕业,另一方面我已经在15年感受了一次。 

苏黎世

苏黎世并不是瑞士首都,说到底我去苏黎世也不是逛市中心,毕竟瑞士的美景都在乡村。但苏黎世这个中文译名读起来特别好听。苏黎世的轻轨非常发达,周边的山非常适合徒步,在酒吧感受了一次裸女阐释的答答主义,会见了大学朋友,体会了高昂物价也就心满意足了。

卢塞恩

一个欧洲旅行团必经过的瑞士城市,距离苏黎世半小时火车距离的小镇。卢塞恩真正的魅力不在于城市而在于旁边的山:皮拉图斯山。放弃坐缆车上山让我们有机会在山间树木和溪流中穿行。

圣加仑

圣加仑是我们返回瓦杜兹经过的一个城市,当时抵达的时间已是傍晚,太阳即将下山。或许是周末的原因,所有商铺除了麦当劳都关门了。我们游逛完教堂后偶遇一个魔术表演。小镇上的人围坐在夕阳下舞台的凳子前,旁边伫立的大树在金色阳光下熠熠生辉,手风琴背景音乐似乎就在描写这个小镇的一点一滴。如果还有时间,我必定驻留一晚来感受这种无声的幸福和安详。

瓦杜兹

瓦杜兹是列支敦士登的首都,也是欧洲游的一个热门附加城市。在我印象中瓦杜兹的城堡,草地和盘山公路非常美丽。瓦杜兹并没有很标志性的建筑风格,却有着漂亮的邮票。在我们旅途的过程中就有大批游客在纪念品店里选购邮票。我自己也挑了一张邮票和一枚纪念币。

克拉科夫

从漫长的历史来说波兰是和俄罗斯,德国结下梁子的国家,这也难怪我能从克拉科夫感受到一些前苏联的影子。建筑物青色的塔尖,铁轨的功能性构造,形似欧洲的建筑和略微简单的公共设施。在旅程中克拉科夫算是一个歇脚地,我们从克拉科夫去往威利奇卡盐矿和奥斯维辛集中营,只有最后一晚才在广场圣诞集市和肖邦钢琴音乐会的急促有力的琴声中感受到这个城市和这个国家。

扎科帕内

扎科帕内于我而言是这趟中欧旅行中最鲜明的记忆。一下车的漫天繁星让我发现星光真的能照亮夜路。木屋和积雪让我置身于一个个小童话中。两天的攀爬雪山和雪地徒步让我不再对冰天雪地陌生。

摄于波兰扎科帕内 2016.12.20

布拉格

布拉格是我们中欧旅游的起点和终点,布拉格记忆里都寒冷和潮湿,第一天和最后一天都在不停的下雨。布拉格唯一让我兴奋不已的其实不在于老城广场的壮阔和城堡的宏伟,而是坐在电车在一个个建筑拱门中穿梭,感觉置身于一个偌大的游乐场。

波尔图

波尔图的印象是风,阶梯和鳕鱼。葡挞反而并没有让我印象深刻。西侧临海的波尔图或许是大风的原因,连接波尔图和加亚新城大桥上的风甚至要把我吹倒。波尔图市区地势很高,我住的地方临河地势很低,每天出门都要爬很多的阶梯才能到达另外一个地方,这竟然让我想到了澳门。鳕鱼也是波尔图,或者说是葡萄牙一大特色,据闻有上百种做法。我尝了几味,味道不浓但精致,配上玫瑰酒或者白葡萄酒感觉还是很赞的。

马德里

马德里作为中规中矩的一个大首都,更适合工作和发展而非旅游。如果非得说一下有什么值得回味,马德里也有许多景点和博物馆。旅途中马德里给我最大感受的就是葡萄牙王国当年的皇家气派:马德里皇宫和马约尔广场就足以证明。

巴塞罗那

如果是球迷的巴塞罗那绝对逛都逛不够,当然吃货也逛不够。虽然巴塞罗那没有法国那样精致美味的出品,但是有简单粗暴的大盘海鲜和海鲜饭也是极好的。建筑控或许真的要来一趟巴塞罗那,不为了吃就是为了把高迪的每一件作品逛一遍,收获或许就不止味蕾的回味,更是视觉的震撼和想象力的爆发。我最近在看新上的港剧<幕后玩家>, 里面Ted画的鱼缸灵感正是当时我游览的米拉之家里海洋般的建筑内饰的来源。

布达佩斯

布达佩斯市中欧旅游经过的一个城市,在结束了漫长的隔夜巴士后果断去泡了一个上午的温泉和桑拿,所有的疲惫和不悦都一并消除。我们在布达佩斯停留的时间不长,印象最深刻的恐怕是冰雪中的室外温泉。我们在布达佩斯度过了平安夜,努力凑钱买的汤圆还没有国内永旺超市买的好吃。国外的月亮比国内圆么我不知道,但国内汤圆倒是比国外圆,又圆又大,囊括了整个家乡和亲朋好友。

上海

2016年到访上海(准确来说是上海浦东机场)的唯一原因是改签航班。就在我庆幸法航终于从巴黎起飞后,我并没想到行李滞留在巴黎。在办理了行李报失和改签航班以后我和少爷在机场度过了一个晚上。或许是因为倒时差的原因,又或许是因为即将归家的原因,我从心底并没有太大的怨气,也没有疲惫不堪。待到上午6点柜台check in的时候,我们排在不断被插队和大声喧哗的队伍里,我尴尬又兴奋地想到,我就要回去了。

北京

帝都终究是要一睹,即便小时候跟着家人参团游览过北京所有的著名景点,但算上时间已经相隔了十几年。或许如帝都出租车司机说的:旅游干嘛来北京,去四川云南不更好?但他或许不知道,在游历了些许国家的首都和大城市后,我只想重新温习一下我的北京。它的魅力是和经历和认知挂钩的,举例来说我就在旅途中体会到南山南北海北到底是什么。行走在南锣鼓巷,三里屯或是商圈里,听着字正腔圆的普通话,吃着包子送着豆浆仿佛置身于国产电影中的某一布景里。除开不会出现在荧屏的雾霾令我稍显吃惊以外,这些镜头般的场景就是我对北京所有好感的源头。

期盼

期盼总是年年都有的,或者每时每刻的存在心里。只是某个特殊的时刻掏出来表示和激励。想起跨年的感觉每一年都不一样,生活和身边的人事在改变也影响着自己的愿望。私心总会有但也是有一些实际而又长久的期盼可以公开而毫无忌讳地写出来呢:

更效率的计划: 在2016年有了很多计划但实际性导致自己积极性不高,很多都搁置了,希望新的一年里更有效率的计划才能让我稳步前行。
更健康的自己: 生病才是最大的拖延。经历了2次生病应该更加注重锻炼来对付更多事务!
不改变的愿望: 最后还是希望家里人健健康康,感情顺利,跟所有朋友都能保持最好的联系

或许2017年我便将真正迈入职场,真心祝愿自己能一切顺利

最后

祝各位新年快乐