Blog

统计文件中单词出现的频率信息(defaultdict)

Content #

下面的Python代码用于统计文件中单词出现的频率信息(记录单词出行的行号及列号),为方便处理找不到的键,代码中使用了defaultdict。

import sys
import re
import collections
WORD_RE = re.compile('\w+')
index = collections.defaultdict(list)
with open(sys.argv[1], encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
      for match in WORD_RE.finditer(line):
         word = match.group()
         column_no = match.start()+1
         location = (line_no, column_no)
         index[word].append(location)
# print in alphabetical order
for word in sorted(index, key=str.upper):
  print(word, index[word])

From #

统计文件中单词出现的频率信息(setdefault)

Content #

下面的Python代码用于统计文件中单词出现的频率信息(记录单词出行的行号及列号),其中有标记的三行代码需要两次查询字典,我们可以将其改写成只有一行代码,且不必于次查询字典。

import sys
import re
WORD_RE = re.compile('\w+')
index = {}
with open(sys.argv[1], encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
      for match in WORD_RE.finditer(line):
         word = match.group()
         column_no = match.start()+1
         location = (line_no, column_no)
         occurrences = index.get(word, []) #BAD
         occurrences.append(location)      #BAD
         index[word] = occurrences         #BAD
# print in alphabetical order
for word in sorted(index, key=str.upper):
    print(word, index[word])

改写方法:

index.setdefault(word, []).append(location)

From #

用iter方法逐行读取文件

Content #

下面的Python代码逐行读取文件,直到遇到空行或者到达文件末尾为止:

with open('mydata.txt') as fp:
  for line in iter(fp.readline, ''):
    process_line(line)

From #

Risk Ratio

Content #

The ratio between probabilities in different groups is called risk ratio, where risk refers to the risk of having the effect. risk = group rate / global rate

If the risk is lower than 1, the group has lower risks: the churn rate in this group is smaller than the global churn. If the value is higher than 1, the group is risky: there’s more churn in the group than in the population.

...

Numerical Instability Issues

Content #

线性回归权值公式: \[w=\left(X^TX\right)^{-1}X^Ty\] 在添加新的特征时,新加的列有可能会是前几个列的组合,这种情况下,矩阵$X^TX$可能会是奇异的,无法求出逆矩阵。

现实中,新的列可能不会正好是其他列的组合,数据会有噪声,矩阵不是奇异的。然而求出的权重可能会有个别分量值特别大的情形。这种现象称为 Numerical Instability Issues.

解决办法是使用正则化技术(Regularization Techniques). 正则化的目的是为了让矩阵可逆。正则化在机器学习中意味着“控制”,即控制模型的权重(weights),使其不至于过大。

Ridge Regression的做法是将矩阵的对象元素添加增量: \[w=\left(X^TX+\alpha I\right)^{-1}X^Ty\] 用NumPy来实现:

XTX = X_train.T.dot(X_train)
XTX = XTX + 0.01 * np.eye(XTX.shape[0])

From #

批处理模式与随机梯度下降法

Content #

当可用的训练样本有多个时,样本的使用模式就分为两种。

一种是批处理模式(batch processing),即计算出在每个样本上目标函数的梯度,再将不同样本的梯度进行求和,求和的结果作为本次更新中目标函数的梯度。在批处理模式中,每次更新都要遍历训练集中所有的样本,因而运算量较大。

另一种模式叫做随机梯度下降法(stochastic gradient descent),它在每次更新中只使用一个样本,下一次更新再使用另外一个样本,在不断迭代的更新过程中实现对所有样本的遍历。有趣的是,事实表明当训练集的规模较大时,随机梯度下降法的性能更佳。

Viewpoints #

From #

04 数学基础 | 不畏浮云遮望眼:最优化方法

实现幂等的两个思路

Content #

实现幂等的方法,无非是两大类:

  1. 通过一些精巧的设计让更新本身就是幂等的,这种需要点儿运气,不是所有业务都适用的。
  2. 利用外部的、具备一致性的存储(比如说MySQL)来做冲突检测。

From #

商品详情页的存储

Content #

商品系统的存储需要提供商品的基本信息、商品参数、图片和视频以及商品介绍等等这些数据。商品的基本信息和商品参数分别保存在 MySQL 和 MongoDB 中,用 Redis 作为前置缓存,图片和视频存放在对象存储中,商品介绍随着商详页一起静态化到商详静态页中。

我把商品系统的存储绘制成下面这张图:

图中实线表示每访问一次商详页,需要真正传输的数据,虚线表示当商详页数据发生变化的时候才需要进行一次数据传输。用户打开一个 SKU 的商详页时,首先去 CDN 获取商详页的 HTML,然后访问商品系统获取价格等频繁变化的信息,这些信息从 Redis 缓存中获取。图片和视频信息,也是从对象存储的 CDN 中获取。

分析一下效果,数据量最大的图片、视频和商品介绍都是从离用户最近的 CDN 服务商获取的,速度快,节约带宽。真正打到商品系统的请求,就是价格这些需要动态获取的商品信息,一般做一次 Redis 查询就可以了,基本不会有流量打到 MySQL 中。

这样一个商品系统的存储的架构,把大部分请求都转移到了又便宜速度又快的 CDN 服务器上,可以用很少量的服务器和带宽资源,抗住大量的并发请求。

Viewpoints #

From #

02 | 流量大、数据多的商品详情页系统该如何设计?

使用电子邮件沟通的技巧

Content #

电子邮件作为一种通信手段有什么好处呢?“非常糟糕。”大多数人这样说。原因之一是电子邮件不包含任何语气,电子邮件的语气视收件人当时的感受而定。如果收件人当时处于自卫防护状态,他们也许会认为你在攻击他们。所以,如果可能的话,亲自和对方见面或进行电话交谈,这显然要好得多。

如果你不得不使用电子邮件进行沟通,那么,怎样做才能使问题最小化呢?下面是一些建议:

• 添加语气。开头这样写,“请把此电子邮件看作……”。然后插入这样的字眼,如“友好”、“建设性的批判”、“难过”、“失望”等。这样会使收件人更有可能以你所期望的语气阅读电子邮件。至少,负面反应会因此减弱。

• 千万不要根据你对所收到电子邮件的第一反应回复电子邮件。大多数人都知道要避免这一点,但很少有人能做到。你本想一吐为快或节约时间。事实上,与立即回复邮件,然后再花几个小时或几天时间来纠正给对方造成的错误印象相比,克制自己、半小时后再看一遍的做法会节约更多时间。

• 在发送电子邮件之前,重新阅读一遍,想象一下对方在心情最糟糕的情况下阅读这封电子邮件的情况。大多数电子邮件给对方留下的印象都比你预想的更咄咄逼人。你应该想一想在最糟糕的情况下对方脑海中的画面。这样做会大大减少风险。

• 进行角色互换。在电子邮件中首先提一些与对方有关的事情——相当于聊天。“希望你感冒已经好了。”“听说你那里下大雪了。”这样做会让你更富有人情味,也会使其更像一次有着更多人际交流的面对面的会谈。

• 心烦或生气的时候千万不要发送电子邮件。因为你会说出一些原本不想说的话。如果可以,先写好电子邮件并保存为草稿,过些时候再重新读一遍。

• 尽量使电子邮件简短些。如果你要提一些需要花很长时间进行检查的复杂建议,电子邮件并非最佳手段。如需发送报告,请以附件形式发送,标出你希望对方阅读的时间段(“在您方便的时候”或“在未来几天之内”)。这样做既考虑了对方的时间,也不至于使对方一拍脑门说:“噢,天哪,又是一封长长的邮件!”

• 如果你正在写一封特别敏感的电子邮件,在发送之前请找一位同事或朋友先检查一遍。另一双眼睛的视角通常会对你有很大帮助。

• 如果不得不在心情不好的时候发送电子邮件,应主动向对方说明。邮件开头可以这样写,“我现在的心情真的非常糟糕,所以请原谅我的语气”,或其他任何需要对方谅解的话。

• 幽默非常有效,但前提是对方看待幽默的方式与你相同。幽默风趣的语句就像聊天一般令人感到轻松。

最后,想想对方的沟通方式,尽可能与其接近。这并不是要你刻意模仿他们,而是在为对方做出转变。

如果对方是一名工作繁忙的高管,他/她也许只会看寥寥数语。关键是要确保对方看到了你想让他们看到的内容。你采用的沟通方式在此会起很大作用。

为比尔·科格里安内斯(Bill Coglianese)的婚礼设计邀请函的设计师,晚了一个多星期还没交上设计样品,而且只有通过电子邮件才能联系上他。这位设计师的助理让比尔再等一星期。比尔没有匆忙地给予对方愤怒的回应,而是发送了一封电子邮件,感谢设计师为他设计婚礼邀请函。接着,他以实事求是的态度告诉对方婚礼带给自己的各种压力,说自己和未婚妻真的需要对邀请函的样式做出决定。他想知道,设计师怎样才能帮助他们完成这个计划?

第二天,比尔拿到了连夜快递来的设计样品。“即使在一封电子邮件中,对待延误也不必态度粗鲁。”比尔说。他还补充说,那封电子邮件不带任何情绪,轻松地就让设计师采取了迅速而积极的行动。

From #

沃顿商学院最受欢迎的谈判课

你为什么认为我是个白痴呢?

Content #

“你是个白痴吗?”对这句话的正确反应是什么?你想的也许是“去你的吧!”,或者“你才是个白痴呢!”,或者“你去死吧!”。所有这些反应都是错误的。正确的反应是:“你为什么认为我是个白痴呢?”

这种反应为什么正确呢?首先,这能让你获得有利于本次或下次谈判的信息。最出色的谈判者都是头脑冷静的,会继续从对方那里获取信息。

如果有人对你说“我恨你”,你要问他为什么。尽量多问对方喜欢什么样的竞争对手,少询问对方对自己的看法。如果对方威胁你,要问他们为什么如此生气。既要看到对方在表达自己情感方面所做的努力——尽管这种努力往往是无效的——并对其做出回应,还要发现对方的言外之意并做出回应。即使对方只向你透露一点点信息,你也可以获取能用来说服他们的宝贵信息。

From #

沃顿商学院最受欢迎的谈判课