第三方开发的Julia库(包),是Julia生态中极为重要的一部分。Julia包虽然目前没有Python那样丰富,但却极为快速地发展着。官方提供了包数量的统计趋势,见下图所示:
由图可见,Julia包的发展非常之快。相信在不久的将来,其丰富性及多样性能够覆盖开发中的各种场景,并能够快速渗透到科学计算等领域。读者可在
https://pkg.julialang.org/
这个网站的近两千个包中寻找适合自己的包。
下面我们将列举一些常用包,关于它们的详细使用方法,请参阅官方文档。
Documenter.jl
这是一个由官方维护的包,专门用于将Julia代码中的注释系统(Docstrings)及其中的Markdown文件生成完整的说明文档。
该包提供的文档生成器,具备以下功能特点:
- 支持Markdown语法
- 开箱即用(Minimal Configuration)
- 支持Julia 0.6及0.7-dev版本(截止书稿时)
- 会对注释中标注的代码执行测试语句(Doctest)
- 支持文档章节等方面的交叉引用
- 支持LaTeX语法
- 文档字符系统缺失与交叉引用错误的检查
- 自动生成目录与文档索引
- 使用Git自动构建与部署文档,并能推送到GitHub的文档库中
包Documenter.jl是已经注册的包,安装很简单,只需执行Pkg.add(“Documenter”)命令即可。该包会将代码库的Markdown文件及代码中以docstrings方式注释的文档系统解析合并为单一的内联(inter-linked)文档。
DataFrames.jl
在科学计算中往往需要综合多种库的优势,以构造强大的应用与分析系统,一个通用的数据结构便成为整合这些不同库的纽带,能够为跨库调用带来极大的便利,更是为生态的快速发展奠基了基础。
在Python语言中,有一个专门用于处理行列式或表格式(tabular)数据的结构,名为DataFrame,是科学计算库Pandas的重要组成部分,已成为很多Python第三方包支持的基本数据操作框架。
类似地,Julia语言的DataFrames库,正是意图建立这样一个基础的数据结构。通过Pkg.add(“DataFrames”)命令便可安装该包,此后使用using DataFrames即可将该包导入到开发者的名字空间中,使用DataFrames中的各种功能。
DataFrame类型能够表达表格式数据,并支持数据中存在缺失值。其内部是列存储的,每列是一个向量结构。在构建DataFrame对象时,可以同时列名,例如:
julia> using DataFrames
julia> df = DataFrame(A = 1:4, B = [“M”, “F”, “F”, “M”])
4×2 DataFrames.DataFrame
│ Row │ A │ B │
├───┼──┼──┤
│ 1 │ 1 │ M │
│ 2 │ 2 │ F │
│ 3 │ 3 │ F │
│ 4 │ 4 │ M │
在构造方法中,参数名即是列名,而参数值即是对应列的取值。例中的DataFrame对象有两列:第一列名为A,取1到4的整型;第二列名为B,值是字符串类型;而列Row是默认添加的行编号。
我们可以通过一些函数查看DataFrame对象的属性:
julia> size(df) # 取得DataFrame对象的行与列数
(4, 2)
julia> size(df,1) # 取得对象的行数
4
julia> size(df,2) # 取得对象的列数
2
也可以通过describe()函数取得基本统计信息:
julia> describe(df)
A # 列名
Summary Stats:
Mean: 2.500000 # 均值
Minimum: 1.000000 # 最小值
1st Quartile: 1.750000 # 分位数
Median: 2.500000 # 中值
3rd Quartile: 3.250000 # 分位数
Maximum: 4.000000 # 最大值
Length: 4 # 行数
Type: Int64 # 数据类型
B
Summary Stats:
Length: 4 # 行数
Type: String # 数据类型
Number Unique: 2 # 唯一值(去重后)的数量
当然,我们可以通过列名,提取出某列的向量:
julia> df[:A]
4-element Array{Int64,1}:
1
2
3
4
julia> df[:B]
4-element Array{String,1}:
“M”
“F”
“F”
“M”
需要注意的是,代码中使用列名时,需使用Symbol类型表达。
CSV.jl
简单的数据交换与存储,可采用CSV格式,这是一种常用的表格式数据,而包CSV.jl专为CSV文件的读写提供了支持。
通过Pkg.add(“CSV”)后,即可使用该包。该包非常简单,基本上就两个操作,read()和write()函数。我们下面仅以read()函数为例,介绍该包的使用。
函数read()会从指定的文件中加载csv格式的数据,并存储到指定的数据结构中,默认的结构为DataFrame类型,其原型为:
CSV.read(fullpath::Union{AbstractString,IO}, sink::Type{T}=DataFrame, args…; kwargs…)
CSV.read(fullpath::Union{AbstractString,IO}, sink::Data.Sink; kwargs…)
其中fullpath指定csv文件的绝对路径,或者是已经打开的某个IO对象。其中的Data.Sink是第三方包DataStreams.jl提供的类型,可参阅相关文档,这里以DataFrame类型为例。
假设有一个csv文件,其内容如下表,各列以英文逗号分隔:
|
|
|
|
|
|
|
|
|
|
|
|
通过CSV包读取,便可将该csv文件的内容加载到一个DataFrame对象中,即:
julia> using CSV
julia> data = CSV.read(“d:/test.csv”)
3×3 DataFrames.DataFrame
│ Row │ c1 │ c2 │ c3 │
├───┼───┼──┼───┤
│ 1 │ 11 │ 7.2 │ abc │
│ 2 │ 12 │ 8.4 │ def │
│ 3 │ 13 │ 9.3 │ ghi │
之后,便可基于DataFrames包的功能进行各种后续操作,例如describe()查看基本情况:
julia> describe(data)
c1
Summary Stats:
Mean: 12.000000
Minimum: 11.000000
1st Quartile: 11.500000
Median: 12.000000
3rd Quartile: 12.500000
Maximum: 13.000000
Length: 3
Type: Union{Int64, Missings.Missing}
Number Missing: 0
% Missing: 0.000000
c2
Summary Stats:
Mean: 8.300000
Minimum: 7.200000
1st Quartile: 7.800000
Median: 8.400000
3rd Quartile: 8.850000
Maximum: 9.300000
Length: 3
Type: Union{Float64, Missings.Missing}
Number Missing: 0
% Missing: 0.000000
c3
Summary Stats:
Length: 3
Type: Union{Missings.Missing, String}
Number Unique: 3
Number Missing: 0
% Missing: 0.000000
从例中可见,CSV能够自动识别出每列的数据类型.
假设上例中的数据有一个缺失值,并以N字符表示,如下表所示:
|
|
|
|
|
|
|
|
|
|
|
|
在读取数据时,设置missingstring参数[
[1]
]为N,告知read()函数有缺失值:
julia> data = CSV.read(“d:/test.csv”; missingstring=”N”)
3×3 DataFrames.DataFrame
│ Row │ c1 │ c2 │ c3 │
├───┼──┼────┼───┤
│ 1 │ 11 │ 7.2 │ abc │
│ 2 │ 12 │ missing │ def │
│ 3 │ 13 │ 9.3 │ ghi │
可见,在获得的DataFrame中,列c2中的缺失值得到了正确的识别。
另外,通过read()函数的键值参数还可以告知csv的其他各种格式情况,以便在加载数据时能够成功处理。下面给出该函数的其他一些使用示例:
# 读取以空白符为分隔符的文件
CSV.read(file; delim=’ ‘)
# 自定义列名,适用于文件中没有提供表头的csv文件,但需要列名的数量与文件的列数一致
CSV.read(file; header=[“col1”, “col2”, “col3”])
# 自定义每列的数据类型,但必须与实际的数据匹配
CSV.read(file; types=[Int, Int, Float64])
# 自定义读取的文件行数,有助于提高解析速度,并可用于只读取所需的有限头部数据
CSV.read(file; rows=10000)
JSON.jl
在数据交换中,尤其是网络数据中,Json格式的使用非常频繁,Julia同样提供了一个简洁的库,用于处理这类格式的数据。
假设有个名为s的字符串变量,存储着Json数据,如下所示:
{
“a_number”: 5.0,
“an_array”: [“string”, 9],
“inner”: {
“value”: 3
}
}
在安装JSON包后,可以尝试将其解析到数据结构,语句非常简单:
julia> s = “{\”a_number\” : 5.0, \”an_array\” : [\”string\”, 9], \”inner\”: {\”value\”: 3}}”;
julia> j = JSON.parse(s)
Dict{String,Any} with 3 entries:
“an_array” => Any[“string”, 9]
“a_number” => 5.0
“inner” => Dict{String,Any}(Pair{String,Any}(“value”, 3))
函数parse()会将s的内容分析出来,放在一个嵌套的Dict对象中,并会自动进行数据类型识别,然后就可以通过关键字进行层层提取了。
julia> j[“an_array”]
2-element Array{Any,1}:
“string”
9
julia> j[“inner”]
Dict{String,Any} with 1 entry:
“value” => 3
julia> j[“inner”][“value”]
3
反之,也可以将对象结构转换到Json字串,便于存储或传输:
julia> JSON.json(j)
“{\”an_array\”:[\”string\”,9],\”a_number\”:5.0,\”inner\”:{\”value\”:3}}”
Taro.jl
这是一个基于Apache Tika等库开发的用于从Word、Excel或PDF文件中提取内容的强大的库,其有以下几个功能点:
- 能够从Word、Excel、PDF文件中提取原始的文本数据
- 从Excel文件中将数据提取到DataFrame结构中
- 以Julia语言读取Excel文件的API接口函数
- 将采用XSL-FO布局的文件转换为PDF文件
Gadfly.jl
包Gadfly是Julia语言开发的绘图与可视化库,由Daniel C. Jones设计,现在由社区维护,其特点包括:
- 相当于SVG、PNG、Postscript与PDF的图形渲染质量
- 直观的、一致性的绘图接口设计
- 可在IJulia中使用
- 能够使用DataFrames.jl数据结构
- 支持大量的绘图类型
Gadfly采用了一种被称为“图形语法(grammar of graphics)”的标准进行架构的设计,其在绘图命令(plot specification)提交后,会遵循内部的流水线进行渲染,得到最终的结果。
渲染流水线(rendering pipeline)会将绘图命令转为一个整体性的图形场景,包括坐标轴、颜色等导引元素(guides),及分层的点、线等图形元素(geometry)。每一层会包括数据源、图形元素(简称图元)、数据与图元的关联映射、应用于层次数据统计等部分。所有的层共享如下元素:坐标系(如笛卡尔坐标系、极坐标系等)、坐标轴的缩放(如重对数、半对数等)、图形场景统计及导引元素等。
一套完整的的绘制命令需要描述清楚这些共享的元素及各层的规格(specifications)。完整的渲染进程如图所示:
ECharts.jl
ECharts是一款由百度前端技术部开发的,基于Javascript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。提供大量常用的数据可视化图表,底层基于
ZRender
(一个全新的轻量级canvas类库),创建了坐标系,图例,提示,工具箱等基础组件,并在此上构建出折线图(区域图)、柱状图(条状图)、散点图(气泡图)、饼图(环形图)、K线图、地图、力导向布局图以及和弦图,同时支持任意维度的堆积和多图表混合展现。
包ECharts.jl基于Julia语言对JavaScript的ECharts 4进行了封装,从而能在Julia中使用这个强大的图表库。在Pkg.add(“ECharts”)之后,即可通过using ECharts使用该包。
例如我们要绘制一个柱状图:
using ECharts
x = [“Monday”,”Tuesday”,”Wednesday”,”Thursday”,”Friday”,”Saturday”,”Sunday”]
y = [11, 11, 15, 13, 12, 13, 10]
bm = bar(x, hcat(0.95 .* y, 1.25 .* y, y))
则会获得下图:
也可以绘制金融当中常见的K线图:
using ECharts
dt = [“2016/08/26”, “2016/08/29”, “2016/08/30”, “2016/08/31”, “2016/09/01”, “2016/09/02”,
“2016/09/06”, “2016/09/07”, “2016/09/08”, “2016/09/09”, “2016/09/12”, “2016/09/13”,
“2016/09/14”, “2016/09/15”, “2016/09/16”, “2016/09/19”, “2016/09/20”, “2016/09/21”,
“2016/09/22”, “2016/09/23”, “2016/09/26”]
close_ = [12.38, 12.47, 12.55, 12.60, 12.44, 12.50, 12.67, 12.70, 12.73,
12.38, 12.70, 12.38, 12.14, 12.11, 12.11, 12.11, 12.00, 12.09, 12.18,
12.17, 12.01]
open_ = [12.47, 12.38, 12.46, 12.48, 12.66, 12.53, 12.49, 12.62, 12.50,
12.61, 12.32, 12.53, 12.18, 12.14, 12.05, 12.12, 12.09, 12.08, 12.17,
12.12, 12.12]
high_ = [12.55, 12.50, 12.56, 12.61, 12.72, 12.57, 12.67, 12.75, 12.75,
12.6850, 12.77, 12.68, 12.31, 12.18, 12.13, 12.33, 12.19, 12.11, 12.29,
12.22, 12.12]
low_ = [12.34, 12.38, 12.43, 12.48, 12.35, 12.46, 12.43, 12.62, 12.50,
12.38, 12.28, 12.33,12.11, 12.06, 12.01, 12.0586, 11.96, 12.01, 12.16,
12.12, 12.00]
c = candlestick(dt, open_, close_, low_, high_)
执行获得的图标如下所示:
利用ECharts.jl包,可以绘制更多的图表,读者可以根据官方文档获得更多的帮助。
QML.jl
在图像界面接口(Graphical User Interface,GUI)方面,QT是基于C++开发的跨平台框架,支持包括Windows、Linux、Android、WP、IOS等多种系统平台,是一个笔者非常欣赏的用C++语言开发的GUI套件,其简洁明了的接口和框架,使用起来非常的方便,而且界面控制也非常的容易。借助QT官方提供的QT Creator工具,更能够快速地设计出合用的交互界面。而且,QT不限于开发GUI,更适用于常见场景的应用开发,包括控制台工具、服务器、网络通讯等。该套件提供社区版,开发者只要遵循其协议,可免费使用。
在界面实现时,除了使用C++语言设计交互逻辑外,还可以使用一种类型JavaScript语言的名为QML的脚本语言进行界面设计,而在Julia中,包QML.jl即是通过CxxWrap.jl包提供了Qt5 QML的编程支持。
在采用Julia进行GUI编程时,还可以参看PySide.jl包、Qwt.jl包及Gtk.jl包。
JDBC.jl
数据库的操作在Julia中也非常方便,其中的JDBC.jl包提供了数据库访问的支持。
该包基于JavaCall.jl包的功能,通过Java的接口访问JDBC驱动。提供的API包括两种核心组件,一种是访问JDBC的直接接口,另一种是支持DataStreams.jl的Julia接口。
在使用该包前,需要安装好对应的JDBC,并配置了正确的路径,然后需先对JVM进行初始化,如下:
using JDBC
JDBC.usedriver(“/home/me/derby/derby.jar”) # 路径指向驱动包
JDBC.init() # 或JavaCall.init()
需要注意的是,在使用该包后,需要显式地进行资源释放:
JDBC.destroy() # 或JavaCall.destroy()
另外,在https://github.com/JuliaDatabases中列出了更多关于数据库操作的Julia包,例如SQLite.jl包、ODBC.jl包、PostgreSQL.jl包、MySQL.jl包等。
Distributions.jl
概率分布在科学计算中常常遇到,无论是样本分析、概率表达等。包Distributions则在概率分布方面提供了很好的支持。其功能特点有:
- 矩(包括均值、方差、 偏度、峰度等)的计算,还有熵及其他属性
- 概率密度函数及其对数表达
- 矩生成函数与特征函数
- 样本采样或总体采样
- 最大相似度估计
该包同时还支持多元统计分布、混合模型、假设检验及分布拟合等计算。
Distances.jl
这又是一个强大的包,提供了各种相似性度量函数的支持。所谓相似性度量,是在模式识别与机器学习中必然会用到的基础模块之一,用于评估两个特征向量的距离,即相似性程度。采用何种距离函数,不论是在聚类还是在分类中,都是需要认真考虑并慎重选择的。
该包在相似度计算的实现中,是进行了优化的,相比于粗糙地使用迭代的方式实现距离评估,有着很大的性能优势。有兴趣的,可在官方包中找到对应的Benchmark对比数据。
下面我们列出其支持的所有距离函数,在开发中可自行选择。关于这些距离函数的具体定义,也请读者能够自行找些资料,仔细研究下。
|
|
欧式距离 |
Euclidean Distance |
平方欧式距离 |
Squared Euclidean Distance |
街区距离 |
Cityblock Distance |
杰卡德距离 |
Jaccard Distance |
Rogers-Tanimoto距离 |
Rogers-Tanimoto Distance |
切比雪夫距离 |
Chebyshev Distance |
闵可夫斯基距离 |
Minkowski Distance |
海明距离 |
Hamming Distance |
余弦相似度 |
Cosine Distance |
相关系数 |
Correlation distance |
卡方距离 |
Chi-square distance |
KL散度 |
Kullback-Leibler divergence |
标准化KL散度 |
Generalized Kullback-Leibler divergence |
瑞利散度 |
Rényi divergence |
JS散度 |
Jensen-Shannon divergence |
马氏距离 |
Mahalanobis distance |
平方马氏距离 |
Squared Mahalanobis distance |
巴氏距离 |
Bhattacharyya distance |
黑林格距离 |
Hellinger distance |
半正矢距离 |
Haversine distance |
平均绝对偏差 |
Mean absolute deviation |
均方差 |
Mean squared deviation |
均方根偏差 |
Root mean squared deviation |
标准化的均方根偏差 |
Normalized root mean squared deviation |
布雷柯蒂斯相异度 |
Bray-Curtis dissimilarity |
另外,这些相似性度量,在包中的具体实现还会有很多的变体,有着更为丰富的选择。笔者提醒,在使用这些距离函数时,最好能很清楚这些函数的定义方式,最为重要的一点是,这些距离函数的计算结果,是越大越表示相似,还是越小越表示相似。
TensorFlow.jl
该包是对Google开发的深度学习库TensorFlow的封装,只需执行
Pkg.add(“TensorFlow”)
即可安装该包。若要在Linux上支持GPU加速,可设置环境变量TF_USE_GPU为1,然后重新编译,即:
ENV[“TF_USE_GPU”] = “1”
Pkg.build(“TensorFlow”)
该包现已支持的功能有:
- 所有基本的一元及二元数学函数或运算符;
- 最常用的神经网络操作,包括卷积、GRU版的循环神经网络及dropout等;
- 神经网络训练模块,例如AdamOptimizer等;
- 基本的图像加载及缩放操作;
- 控制逻辑操作;
- PyBoard图可视化。
Mocha.jl
包Mocha是Julia语言实现的深度学习框架,类似于C++中的Caffe库。Mocha高效地实现了常见的随机梯度优化和通用层,通过无监督的自编码器的学习方式,可用于训练深度神经网络(Deep Neural Networks,DNN)和卷积神经网络(Convolutional Neural Networks,CNN)。Mocha的特点有:
- 模块化的架构。Mocha有着清晰的组织结构,而且各个组件间是低耦合的(isolated)。这些模块包括网络层、激励函数、优化过程、正则化函数、初始化函数等。内置的组件已足够用于典型的DNN或CNN应用,而开发者更可在其基础上进行类型扩展。
- 高层接口。借助Julia语言强大的表达能力及迅速发展的开源生态,在Mocha中使用DNN等功能会很容易、自然。可通过提供的图像分类案例进行方便的学习。
- 可移植及高性能。Mocha因为基于Julia语言,故可运行于任何支持Julia语言的平台上,而且这种移植性对于开发者来说是透明的。基于Julia语言JIT编译器与各种内置的性能函数,可以很方便、高效地进行算法的原型设计,并能够直接获得性能评估。而且,在C++编译器可用时,原生扩展后端打开后能够比纯粹的Julia后台快2到3倍。
Mocha提供的GPU后台使用的是NVidia®的cuDNN库,cuBLAS库及定制的CUDA内核,提供了高性能的计算能力。采用GPU加速后,在现代GPU设备中,特别是在大型模型中,能够获得20到30倍的速度提升。
- 兼容性。借助专用于科学数据存储的HDF5格式,在Mocha用其存储数据集及模型的快照,从而能够很容易地与Matlab、Python(Numpy)及其他已存在的计算库进行数据交换。Mocha同样提供了从Caffe中导入训练模型快照的工具,开发者可以充分利用不同库的优势。
- 可靠性(Correctness)。Mocha中的每个组件都经过了充分的测试,其正确性与可靠性是保证的。
- 开源开放。Mocha采用的MIT(Expat)许可证,其源代码是开源的,开发者可以方便地进行学习,并可自行扩展。
若要安装Mocha库,只需在Julia的REPL中,运行命令:
Pkg.add(“Mocha”)
即可。
[[1]] 旧版CSV包中使用键值参数null指定缺失值的标识字符串,但新版中已弃用,被missingstring代替。
[[2]] 图片来自https://www.oschina.net/p/echarts