正文
frequency
(
speed
: u.meter
/
u.s,
wavelength
: u.m) -> u.terahertz:
return
speed
/
wavelength
frequency(
speed
=
300_000
*
u.km
/
u.s,
wavelength
=
555
*
u.nm)
#
output: 540.5405405405404 THz, frequency of green visible light
如果你需要用Python处理表格类型的科学数据,你可以尝试astropy包,体验一下计量单位随意转换的方便性。你还可以针对某个应用专门定义一个装饰器,用同样的方式来控制或转换输入和输出的计量单位。
通过 @ 实现矩阵乘法
下面,我们实现一个最简单的机器学习模型,即带 L2 正则化的线性回归 (如岭回归模型),来对比 Python2 和 Python3 之间的差别:
# l2-regularized linear regression: || AX - b ||^2 + alpha * ||x||^2 -> min
# Python 2
X = np.linalg.inv(np.dot(A.T, A) + alpha * np.eye(A.shape[1])).dot(A.T.dot(b))
# Python 3
X = np.linalg.inv(A.T @ A + alpha * np.eye(A.shape[1])) @ (A.T @ b)
在 Python3 中,以@作为矩阵乘法符号使得代码整体的可读性更强,且更容易在不同的深度学习框架间进行转译:因为一些代码如
X @ W + b[None, :]
在 numpy、cupy、pytorch 和 tensorflow 等不同库中都表示单层感知机。
使用 ** 作为通配符
Python2 中使用递归文件夹的通配符并不是很方便,因此可以通过定制的 glob2 模块来解决这个问题。递归 flag 在 Python 3.6 中得到了支持。
import glob
# Python 2
found_images = \
glob.glob('/path/*.jpg') \
+ glob.glob('/path/*/*.jpg') \
+ glob.glob('/path/*/*/*.jpg') \
+ glob.glob('/path/*/*/*/*.jpg') \
+ glob.glob('/path/*/*/*/*/*.jpg')
# Python 3
found_images = glob.glob('/path/**/*.jpg', recursive=True)
Python3 中更好的选择是使用 pathlib:(缺少个import)
# Python 3found_images = pathlib.Path('/path/').glob('**/*.jpg')
Python3中的print函数
诚然,print 在 Python3 中是一个函数,使用 print 需要加上圆括弧(),虽然这是个麻烦的操作,但它还是具有一些优点:
print >>sys.stderr, "critical error" # Python 2
print("critical error", file=sys.stderr) # Python 3
# Python 3
print(*array, sep='\t')
print(batch, epoch, loss, accuracy, time, sep='\t')
# Python 3
_print = print # store the original print function
def print(*args, **kargs):
pass # do something useful, e.g. store output to some file
在 Jupyter notebook 中,这种形式能够记录每一个独立的文档输出,并在出现错误的时候追踪到报错的文档。这能方便我们快速定位并解决错误信息。因此我们可以重写 print 函数。
在下面的代码中,我们可以使用上下文管理器来重写 print 函数的行为:
@contextlib.contextmanager
def replace_print():
import builtins
_print = print # saving old print function
# or use some other function here
builtins.print = lambda *args, **kwargs: _print('new printing', *args, **kwargs) yield
builtins.print = _print
with replace_print():
<code here will invoke other print function>
但是,重写print函数的行为,我们并不推荐,因为它会引起系统的不稳定。
# Python 3
result = process(x) if is_valid(x) else print('invalid item: ', x)
f-strings 可作为简单和可靠的格式化
默认的格式化系统提供了一些灵活性操作。但在数据实验中这些操作不仅不是必须的,还会导致代码的修改变得冗长和琐碎。
而数据科学通常需要以固定的格式,迭代地打印出一些日志信息,所使用的代码如下:
# Python 2
print('{batch:3} {epoch:3} / {total_epochs:3} accuracy: {acc_mean:0.4f}±{acc_std:0.4f} time: {avg_time:3.2f}'.format(
batch=batch, epoch=epoch, total_epochs=total_epochs,
acc_mean=numpy.mean(accuracies), acc_std=numpy.std(accuracies),
avg_time=time / len(data_batch)
))