最近有个奇怪的需求,批量修改文件的访问和修改时间。原因是在windows下重命名的时候,批量修改了文件的名称。感觉跟说绕口令一样。针对这一需求,尝试利用python的timeos两个库来解决。

查看文件的历史时间

首先基于如下代码查看文件的创建修改最后访问时间,即

1
2
3
4
5
6
7
8
import time
import os
filepath = "./file.xxx"
# 查看文件时间戳
time_create = os.path.getctime(filepath)
time_modify = os.path.getmtime(filepath)
time_access = os.path.getatime(filepath)

若需要得到格式化的时间,可以利用time.ctime()函数获取,例如

1
2
3
print(time.ctime(time_create))
Mon Jun 13 07:34:19 2016

修改文件的创建和修改时间

由于恢复的文件名以后,文件的修改时间发生了变化,需要对其时间戳进行修改,此时采用os.utime()方法来实现,例如

1
2
3
new_access_time = xxx # 注意这里需要是整数
new_modify_time = xxx # 注意这里需要是整数
os.utime(filepath, (new_access_time, new_modify_time))

References

[1] python如何不改动文件的情况下修改文件的 修改日期

Comment and share

简单记录一下python读入tiff多通道图像的方法。尝试了scipy.misc.imreadcv2.imread等都没有成功,最后找到了用skimage读取的方法。

样例如下,我的图片是一个512x512x30的stack,

1
2
3
4
5
from skimage import io
img = io.imread(imgpath)
img.shape
(30, 512, 512)

Tip

在安装Opencv3的过程中,找到了一个比较简单的方法。。。也可能是已经进入python的库了吧。

1
pip3 install opencv-python

以前为什么那么麻烦。。。

Reference

Comment and share

简单记录一下matplotlib显示中文乱码的问题,参考了这篇博客。解决方法有两种,其中方法一成功了,第二种还是有点问题。。。

方法一

首先,查看已经安装的中文字体,如下

1
2
3
4
5
6
7
8
$ fc-list :lang=zh
/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc: Noto Serif CJK TC:style=Regular
/usr/share/fonts/WinFonts/STXINGKA.TTF: STXingkai,华文行楷:style=Regular
/usr/share/fonts/WinFonts/STCAIYUN.TTF: STCaiyun,华文彩云:style=Regular
/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc: Noto Serif CJK JP:style=Regular
/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc: Noto Serif CJK KR:style=Regular
/usr/share/fonts/X11/misc/wenquanyi_10pt.pcf: WenQuanYi Bitmap Song:style=Regular
/usr/share/fonts/WinFonts/msjhl.ttc: Microsoft JhengHei,微軟正黑體,微軟正黑體 Light,Microsoft JhengHei Light:style=Light,Regular

这里我从Windows下复制了一些字体过来,安装方法比较简答,可以去Google一下。。。

查看字体以后,便可以通过设置FongProperties来实例化用于pyplot显示的字体,这里我选择了微软雅黑。后续在应用时,给出现中文的方法提供fontproperties值,便可以正常显示中文了。当然,其他的罗马字母的字体也会被修改。

1
2
3
4
from matplotlib.font_manager import *
myfont = FontProperties(fname='/usr/share/fonts/WinFonts/msyhbd.ttc')
...
plt.title("中文",fontproperties=myfont)

方法二

第二种方法是将中文字体添加到matplotlib的font中,根据安装位置的不同,可能出现在如下两个位置

  1. /usr/share/matplotlib/mpl-data/fonts
  2. ~/.local/lib/python3.6/site-packages/matplotlib/mpl-data/fonts

将字体文件复制到该路径下,并将字体名添加到matplotlibrc文件的sans-serif行,如下所示

1
#font.sans-serif: Microsoft YaHei, DejaVu Sans, Bitstream Vera Sans, Computer Modern Sans Serif, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif

最后,在应用时,设定rcParams[‘font.sans-serif’]为Microsoft Yahei

1
2
plt.rcParams['font.sans-serif'] = ['Microsoft Yahei']
plt.rcParams['font.family']='sans-serif'

References

Comment and share

简单记录一下最近遇到的一个bug,利用numpy生成的矩阵在复制时不能直接赋值,而是要用copy方法。直接赋值类似于把内存中的地址 (即指针) 给了目标变量,其与被赋值变量共享同一块内存,这样做可以节省内存空间。而copy则不同,会重新申请一块内存,分配给复制后的新变量,在该变量上的操作不会对愿变量产生影响。

下面看一个例子,

1
2
3
4
5
6
7
8
9
10
import numpy as np
x = np.arange(9.).reshape(3,3)
# copy
y = x.copy()
y[y>=5] = 0
# 赋值法
z = x
z[z>=5] = 0

其输出结果如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
In [6]: y
Out[6]:
array([[0, 1, 2],
[3, 4, 0],
[0, 0, 0]])
In [7]: x
Out[7]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [8]: z
Out[8]:
array([[0, 1, 2],
[3, 4, 0],
[0, 0, 0]])
In [9]: x
Out[9]:
array([[0, 1, 2],
[3, 4, 0],
[0, 0, 0]])

可以看到,采用copy后,对y的操作不会影响到原矩阵x,而采用直接赋值后,对z的操作对x产生了影响。

Comment and share

最近写autoencoder的时候,遇到嵌套列表复制和reverse的问题。虽然list提供了copy方法,但涉及嵌套复制时就会出错。例如,

1
2
3
4
x = [[1, 2], 3]
y = x.copy()
y.reverse()
y[1][0] = 2

yx变为,

1
2
x = [[2, 2], 3]
y = [3, [2, 2]]

list.copy()对最外层的列表实现了复制,但内部的列表并没有。解决方法是用copy库中的deepcopy方法,如下

1
2
3
4
5
from copy import deepcopy
x = [[1, 2], 3]
y = x.copy()
y.reverse()
y[1][0] = 2

此时的xy为,

1
2
x = [[1, 2], 3]
y = [3, [1, 2]]

Reference

Comment and share

这两天尝试将一个MATLAB工程转成Python,卡在一个bug上很久,最后发现是二者在矩阵索引上存在区别。这里我采用的是Python的NumPy库。

我们经常会通过一定的逻辑关系索引矩阵中的元素,并获取这些元素的位置信息,即indices。例如,

1
2
3
4
5
6
% MATLAB实现
x = resize(0:8, 3, 3);
% 一维索引
idx = find(x >= 3);
% 二维索引
[idr, idc] = find(x >= 3);

对应的python实现为,

1
2
3
4
5
import numpy as np
x = np.arange(9).reshape(3,3)
# 只有二维索引
[idr, idc] = np.where(x >= 3)

这里可以看出,MATLAB提供一种一维索引,即将二维矩阵以列为先,行次之转为一维向量,输出的索引对应该一维向量中元素所在位置。(这种处理方法经常可以用于加速运算,缩短运行时间。)然而,NumPy的where方法根据矩阵的维数提供对应axis的索引,没有MATLAB这种一维索引的输出。

因此,在python中使用np.where进行矩阵元素索引时,要注意如下两点,

  1. np.where的输出是一个列表;
  2. np.where的输出列表的元素个数与矩阵的维数对应。

Reference

[1] numpy.where

Comment and share

简单记录一下利用python的SciPy库进行曲线拟合的方法,主要分为三个步骤,(1) 获取待拟合数据; (2) 定义函数描述待拟合曲线; (3)利用Scipy.optimize.curve_fit模块进行拟合。

获取数据的步骤不再赘述,这里从步骤二开始。以泊松分布为例,首先定义函数poisson_func

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import math
def poisson_func(k, l, c):
"""Poisson function
inputs
======
k: np.ndarray
number of accidents, i.e., the x axis;
l: double
the lambda parameter of Poisson distribution
c: double
a constant for release the optimization
output
======
the fitted result according to l and c w.r.t. k
note
====
l and c are the parametres to be estimated.
"""
k_mat = np.ones(k.shape)
for x, i in enumerate(k):
k_mat[i] = math.factorial(x)
return l**k / k_mat*np.exp(-l) + c

紧接着,根据待拟合的数据,对参数进行估计,如下

1
2
3
4
from scipy.optimize import curve_fit
popt, pcov = curve_fit(poisson_func, x, y)
perr = np.sqrt(np.diag(pcov))

其中popt为估计的参数,pcov为对应的相关矩阵,其对角线为方差,可用于计算拟合参数的误差perr。

下图为我的测试样例,图中橙色三角为待拟合样本点,蓝色实线为拟合结果。

References

[1] Scipy.optimize.curve_fit
[2] Poisson distribution

Comment and share

python decorator

简单记录一下python修饰符@的理解和使用方法,一直没好好理解,现在卡住了。。。参考wiki的定义, A decorator is any callable Python object that is used to modify a function, method or class defination. The decorator syntax is pure syntactic sugar, using @ as the keyword.即python修饰符作为一种python对象,用来修饰函数、方法或者类。

参考Wiki,我们简单实现一个修饰符的样例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def calculator(f):
print("Begin...")
a = 3.0
b = 2.0
f(a,b)
print("End")
@calculator
def calc_add(a,b):
print("%.2f + %.2f = %.2f" % (a,b,a+b))
@calculator
def calc_minus(a,b):
print("%.2f - %.2f = %.2f" % (a,b,a-b))

在ipython环境下执行,有如下结果,

1
2
3
4
5
6
Begin...
3.00 + 2.00 = 5.00
End
Begin...
3.00 - 2.00 = 1.00
End

所以,修饰符的用途,等价于如下情形,

1
2
3
4
5
6
7
>>> a = 3.0, b = 2.0
>>> print("Begin...")
>>> calc_add(a,b)
>>> print("End")
>>> print("Begin...")
>>> calc_minus(a,b)
>>> print("End")

最直观的理解就是decorator简化了calculator()中的部分代码。正如wiki中的解释:Decorators are a form of metaprogramming; they enhance the action of the function or method they decorate.

这篇博客还分析了修饰符嵌套的执行顺序问题,感兴趣可以参考一下。

References

[1] Python syntax and semantics#Decorators
[2] Python修饰符 (一)—— 函数修饰符 “@”

Comment and share

Libsvm for python

Happy new year!! Feel blue but still have to work.

I am gonna introduce the application of a famous package namely libsvm, which realizes the support vector machin (SVM) based algorithms and supports multiple programming languages. I have designed SVM based approaches for machine-learning tasks on MATLAB by the libsvm, which is very awsome. Now, it’s time to try it on python, though it has been encapsulated in the SciPy.

To use libsvm on python, you may follow the coming steps.

  1. Download the package

    1
    $ wget -O libsvm.tar.gz http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm.cgi?+http://www.csie.ntu.edu.tw/~cjlin/libsvm+tar.gz
  2. unzip the package

    1
    $ tar -xvf libsvm.tar.gz
  3. Installization

    1
    2
    $ cd libsvm-3.22
    $ make

If it generates four svm- prefixed files as well as the library libsvm.so.2, then the installization is completed.

Now you can take a trial with provided python based utilities in the folder ./python. For instance,

1
2
3
4
5
6
7
8
9
10
11
12
>>> from svmutil import *
>>> y, x = svm_read_problem('../heart_scale') # load data
>>> m = svm_train(y[:200], x[:200], '-c 4') # train a SVM model
# This will output like,
*.*
optimization finished, #iter = 257
nu = 0.351161
obj = -225.628984, rho = 0.636110
nSV = 91, nBSV = 49
Total nSV = 91
>>> p_label, p_acc, p_val = svm_predict(y[200:], x[200:], m) # make a test
Accuracy = 84.2857% (59/70) (classification)

Note

As introduced by the README in the ./python folder, two .py scripts are provided, of which svm.py and svmutil.py are corresponding to low-level and high-level use of the interface. In my opinion, I suggest the users to directly use svmutil.py.

In addition, the python scripts rely on the libsvm.so.2, which should be added into the LD_LIBRARY_PATH or a package not find exception will be raised when import svm.

Now, time to do your machine learning work.

Comment and share

Author's picture

Jason Ma

We are in the same story.


Astronomer? Software engineer


Shanghai