如果出现git问题,切换shell模式,执行:
git config --global http.proxy ‘socks5://127.0.0.1:1080’
git config --global https.proxy ‘socks5://127.0.0.1:1080’
# 新建一个DataFrame并增加4列内容
using DataFrames
df1 = DataFrame()
df1[:clo1] = Array([1.0,2.0,3.0])
df1[:clo2] = Array([4.0,5.0,6.0])
df1[:clo3] = Array([7.0,8.0,9.0])
df1[:ID] = Array(['a','b','c'])
show(df1)
>>3×4 DataFrame
│ Row │ clo1 │ clo2 │ clo3 │ ID │
│ │ Float64 │ Float64 │ Float64 │ Char │
├─────┼─────────┼─────────┼─────────┼──────┤
│ 1 │ 1.0 │ 4.0 │ 7.0 │ 'a' │
│ 2 │ 2.0 │ 5.0 │ 8.0 │ 'b' │
│ 3 │ 3.0 │ 6.0 │ 9.0 │ 'c' │
# 如果没有指定列名,则默认是x1,x2...
df2 = DataFrame(rand(5,6))
# 在DataFrame定义时直接指定内容
df3 = DataFrame([collect(1:3),collect(4:6)], [:A, :B])
>> A B
Int64 Int64
1 1 4
2 2 5
3 3 6
RDatasets是Julia中的一个数据集,里面包含了很多可以学习和验证的数据,其中就包括iris数据集。
下面是直接读取csv、xlxs、txt文件的方法
下面是一些基础操作:
注意最后三者的差别。
下面是修改数据的方法:
机器学习库自己可以搜
深度学习库是Flux
首先要关注一下特殊符号,例如eltype函数:
function eltype(::Type{<:AbstractDict{K,V}}) where {K,V}
if @isdefined(K)
if @isdefined(V)
return Pair{K,V}
else
return Pair{K}
end
elseif @isdefined(V)
return Pair{k,V} where k
else
return Pair
end
end
其中:
1.{}用来表示类型的参数化(泛型),比如说Vector{Int}表示一个整数的向量,在Java(以及C++)中用<>表示,例如List
2.[]表示数组
3.()可以表示元组(和Haskell,Python一致),如(1,2,3),也可以表示函数调用,如sum([1,2,3])
3.A<:B表示类型子类化(A是B的子类,a::B表示a的类型是B)
4.where引导类型变量,例如Array{T,3} where T表示一个3维数组,数组元素的类型为某个待定的T,可以提高性能
5.一个点 . ,如A.a,表示A有个属性为a;. 还可以用来表示broadcast,可以理解为就是map,例如说,你有一个矩阵A,sin.(A)表示将A中元素分别求正弦后得到的新矩阵,等价于map(sin,A)
6.@表示宏调用(Julia本来也可以不用@标记宏,但是为了大家方便阅读,最后还是强制要求用@标记)
7.Julia中有生成函数(一种特殊函数),本质上是一个返回表达式的函数,然后表达式会插入函数所在处执行了。这个东西创造出来是为了利用LLVM的多层次编译优势(运行时动态生成优化代码),主要用于优化(而且被大量使用)例如在文档中的例子:
julia> @generated function bar(x)
if x <: Integer
return :(x ^ 2)
else
return :(x)
end
end
bar (generic function with 1 method)
julia> bar(4)
16
julia> bar("baz")
"baz"
避免全局变量,把全局变量声明为常量可以巨大的提升性能。如果必须要声明全局变量,可以在使用它的地方标注他们的类型来优化效率。
任何注重性能或者需要测试性能的代码都应该被放置在函数之中。
可以通过@code来查看用于code generation的宏
下面是测试例子:
global x = rand(10000)
function lp1() # 直接动用全局变量
s = 0.0
for i in x
s += i
end
end
function lp2() # 指定全局变量类型
s = 0.0
for i in x::Vector{Float64}
s += i
end
end
function lp3(x) # 将变量以参数形式传入
s = 0.0
for i in x
s += i
end
end
指定类型是速度最快的,原理如下:
当我们定义一个函数时,如果函数参数的类型是固定的,比如是一个Int64的Array[1,2,3,4],那他们在内存中会连续存放;
但如果函数参数的类型是Any,那么内存中连续存放只是他们的“指针”,会指向其实际的位置。这样一来,数据存取就慢下来了。计算concrete类型会比计算abstract类型要节省时间,我们可以使用@code_warntype来查看运行的函数中是否有abstract类型,对于有abstract类型的地方,会用红色的标出。
可以用如下函数来获得相同的数据类型:
zero(value)
eltype(array)
one(value)
similar(array)
向量化并不会提高Julia的运行速度,@simd 可以在运算支持被重新recorded时加速运算
输出预分配可以提高性能
避免不必要的Array,比如计算x,y,z的和时,使用x+y+z,不要用sum([x,y,z])
用div(x,y)代替trunc(x/y),用fld(x,y)代替floor(x/y),用cld(x,y)代替ceil(x/y),有现成的函数就不要自己写计算过程
pkg> add CUDA
pkg> test CUDA
下面是cuda版本
使用GPU简单到令人感动,pkg中add CUDAdrv即可:
julia> using CUDAdrv
julia> CUDAdrv.name(CuDevice(0))
"Tesla P4"
关于GPU的一些注意事项:
GPU是一个独立的硬件,具有自己的内存空间和不同的架构。 因此,从RAM到GPU存储器(VRAM)的传输时间很长。 即使在GPU上启动内核(换句话说,调度函数调用)也会带来较大的延迟。 GPU的时间约为10us,而CPU的时间则为几纳秒。
较低的精度是默认值,而较高的精度计算可以轻松地消除所有性能增益
GPU函数(内核)本质上是并行的,所以编写GPU内核至少和编写并行CPU代码一样困难,因此许多算法都不能很好地移植到GPU上。内核通常是用C/ C++编写的,这并不是写算法的最佳语言。
CUDA和OpenCL之间存在分歧,OpenCL是用于编写低级GPU代码的主要框架。虽然CUDA只支持英伟达硬件,但OpenCL支持所有硬件,但有些粗糙。