Почему выбирают Юлию?
Когда речь заходит о науке о данных, машинном обучении, глубоком обучении, искусственном интеллекте и т. д., первым инструментом, который приходит на ум, должен быть Python. Я должен сказать, что Python имеет самую надежную экосистему, Numpy, Pandas, matplotlib, sklearn, tensorflow и многое другое. Если вы только начинаете заниматься наукой о данных, машинным обучением, глубоким обучением, искусственным интеллектом, Python, несомненно, лучший выбор. Однако самая фатальная слабость Python — его медленная эффективность — естественным образом обнаруживается: когда он сталкивается с чрезвычайно высокой вычислительной нагрузкой или огромным набором данных, он кажется бессильным.
В настоящее время для повышения эффективности мы подумаем об использовании других языков, таких как Golang, Rust, Java и т. д. Во-первых, и Golang, и Rust — чрезвычайно быстро компилируемые языки, но ни один из них не подходит для науки о данных или искусственного интеллекта.
Golang широко используется в микросервисах, облачных вычислениях и других областях из-за своих уникальных горутин и каналов.Требования Golang к типам переменных слишком строгие, а пакет gonum, используемый для машинного обучения, имеет низкую гибкость.Матрица кажется бессильной, а соединение между пакетом матриц gonum, пакетом алгоритмов golearn и пакетом gota DataFrame — просто головная боль. Что касается Rust, то это язык только что появившийся, его нынешнее состояние очень похоже на Golang через 13 или 14 лет, экология неполная, и программисты больше склонны использовать Rust для микросервисов или системного программирования. Автор более популярного пакета машинного обучения rusty-machine также официально объявил на GitHub, что он больше не будет активно поддерживаться.
Что касается Java, то она слишком громоздка и тяжела.
Джулия имеет чрезвычайно высокую эффективность за пределами языка C, более лаконичный код, чем Python, добавляет некоторые функции в JavaScript (функция стрелки, троичное выражение, асинхронность и т. д.) и даже реализует горутину и канал Golang.
Ниже приведена сравнительная таблица эффективности работы с языком C в качестве единицы измерения.
Поездка о Юлии
Переменная
- Вы можете объявить глобальные переменные, такие как python, но вам не нужно беспокоиться о том, что объявление переменной в начале файла повлияет на глобальную переменную, и вам не нужно беспокоиться о случайном изменении переменной, что приведет к неожиданным результатам, потому что переменные in Julia do Объем контролируется нашими программистами
# 声明全局变量的方式
x = 10
# 我们可以通过关键字global local来控制我们的变量的作用范围
function funscope(n)
x = 0
for i = 1:n
local x
x = i + 1
if (x == 7)
println("这是for循环中的x: $x")
end
end
x
println("这是函数中的x: $x")
# 在这里我们修改了全局变量x
global x = 15
end
funscope(10)
println("这是全局变量x: $x")
# 上面的函数会输出
# 这是for循环中的x: 7
# 这是函数中的x: 0
# 这是全局变量x: 15
- Вы можете объявить переменную с помощью блока кода, как в Rust.
# 下方运算后 x 为 70
x = begin
local a = 10
a * 7
end
# 下方运算后 y 为 70
y = (b = 10; b*7)
-
Вы также можете указать тип переменной.Обратите внимание, что глобальные переменные не могут указывать свой тип.
# 这是错误的行为 # 在外部声明变量默认为global # x::Float64 = 1.2 local x::Float64 = 1.2 # 在函数、循环、条件中声明的变量默认为local function specify_variable_type() x::Int32 = 10 typeof(x) end
Array
Наука о данных и искусственный интеллект неотделимы от матриц.Julia имеет чрезвычайно мощный массив и нативно поддерживает матрицы и различные операции, а это означает, что нам не нужно полагаться на сторонние числовые пакеты, как в других языках (например, Python полагается на Numpy, Golang полагается на gonum и т. д.)
-
матрица
# 创建一个矩阵数组 mat = [1 2; 3 4] # 输出 # 2×2 Array{Int64,2}: # 1 2 # 3 4 mat1 = [1 2] .* [3 4] # 输出 # 2×2 Array{Int64,2}: # 1 2 # 3 4 # 获取矩阵的dimension ndims(mat) # 2 # 获取矩阵的size size(mat) # (2, 2) # 获取矩阵的元素个数 length(mat) # 4 # 创建一个Identity矩阵 using LinearAlgebra idm = Matrix(1*I, 3, 3) # 输出 # 3×3 Array{Int64,2}: # 1 0 0 # 0 1 0 # 0 0 1 # 切片 idmc = idm[2:end, 2:end] # 输出 # 2×2 Array{Int64,2}: # 1 0 # 0 1 # 对矩阵的一部分进行重新赋值 idm[2:end, 2:end] = [5 7; 9 11] idm # 输出 # 3×3 Array{Int64,2}: # 1 0 0 # 0 5 7 # 0 9 11 # 将矩阵进行reshape ridm = idm[:] # 输出 # 9-element Array{Int64,1}: # 1 # 0 # 0 # 0 # 5 # 9 # 0 # 7 # 11 # 获取矩阵的transpose m2 = [1 2; 3 4] m2' # 注意此处的' # 输出 # 2×2 Adjoint{Int64,Array{Int64,2}}: # 1 3 # 2 4 # 矩阵点乘 m2 * m2' # 输出 # 2×2 Array{Int64,2}: # 5 11 # 11 25 # 矩阵相乘 m2 .* m2' # 输出 # 2×2 Array{Int64,2}: # 1 6 # 6 16 # 获取逆矩阵 inv(m2) # 输出 # 2×2 Array{Float64,2}: # -2.0 1.0 # 1.5 -0.5
функция
Функции в Julia исключительно мощные, поддерживают универсальные функции, каррирование, анонимные функции и могут возвращать несколько значений, как функции в Go. Мы даже можем писать функции Julia так же, как код javascript.
-
объявить функцию
# 使用关键字进行声明 function mult(x::Number, y::Number) return x * y end # 使用short-hand的形式声明函数 # 注意在进行数学计算时我们甚至可以省略一些操作符 f(x::Number,y::Number) = 3x - 6y + 12 # 像Rust一样省略return关键字 function div(x::Number, y::Number) x / y end # 像Golang一样返回多个函数值 using Printf function mult_add_divide_subtract(x,y) x * y, x + y, x- y, x / y end m, a, d, s = mult_add_divide_subtract(20, 10) # print 结果为200 30 10 2.0 @printf("%d, %d, %d, %.1f", m, a, d, s)
-
общая функция
Julia поддерживает перегрузку функций, подобно тому, как мы можем объявлять функции с тем же именем в классах Java.
function add(x, y) println("没有指定x,y的类型") x+y end function add(x::Integer, y::Float64) println("x是Integer型, y是Float64型") x + y end function add(x::Float64, y::Integer) println("x是Float64型, y是Integer型") x + y end function add(x::Float64, y::Float64) println("x、y是Float64型") x + y end add(1,2) add(1.0, 2) add(1, 2.0) add(1.0, 2.0) # 输出结果 # 没有指定x,y的类型 # x是Float64型, y是Integer型 # x是Integer型, y是Float64型 # x、y是Float64型 # 我们甚至可以重定义基本的操作符 using Base.+ +(x::Bool, y::Integer, z::Float64) = println("布尔值加整数加浮点数") true + 10 + 2.0 # 输出 # 布尔值加整数加浮点数
-
Каррирование и анонимные функции
Julia поддерживает тернарные выражения, стрелочные функции, каррирование, анонимные функции в JavaScript.
# 三元表达式 fib(n) = n < 2 ? n : fib(n - 1) + fib(n - 2) # 双目运算 negative(n) = n < 0 && println(true) # 打印 true negative(-1) # 返回 false negative(2) # 柯里化 function add(x) return function f(y) return x + y end end add(1)(2) # 箭头函数 arrow = () -> println("我是箭头函数") arrow() arrow1 = x -> println("x是$x") arrow1(10) arrow2 = (x, y, z) -> println("$(x + y + z)") arrow2(2,3,4) # 匿名函数 c = function (x) x + 2 end c(9)
-
Необязательные и ключевые аргументы
# 可选参数 f(a, b = 5) = a+ b f(1) # 6 f(2,7) # 9 # 关键字参数函数 k(;kw = "keyword") = println(kw) # 输出keyword k() # 输出hello k(kw="hello") # 可选参数,关键字参数结合, 轻松的创建key-value对 function varargs3(;args...) args end rst = varargs3(k1="name1", k2="name2", k3=7) rst # 输出 # pairs(::NamedTuple) with 3 entries: # :k1 => "name1" # :k2 => "name2" # :k3 => 7
Канал и сопрограмма
Джулия представляет концепцию сопрограмм Golang для создания собственного уникального канала для операций сопрограмм.
# 下方函数将计算斐波那契数列,把计算好的结果放进channel中
function fib_producer(c::Channel)
a, b = (0, 1)
for i = 1: 5
put!(c, b)
a, b = (b, a+b)
end
end
chnl = Channel(fib_producer)
take!(chnl) # 1
take!(chnl) # 1
take!(chnl) # 2
take!(chnl) # 3
take!(chnl) # 5
# 下方进行阶乘运算,如果你熟悉go语言
# 你会惊讶这几乎就是go语言中goroutine和channel的交互方式!
fac(i::Integer) = (i > 1) ? i*fac(i - 1) : 1
c = Channel(0)
# 此处使用async 进行异步
task = @async foreach(i->put!(c,fac(i)), 1:5)
bind(c,task)
for i in c
@show i
end
# i = 1
# i = 2
# i = 6
# i = 24
# i = 120
Эпилог
Кроме того, Джулия также может вызывать код C и Python. Jupyter Notebook и фреймворк глубокого обучения Tensorflow также полностью поддерживают последнюю версию Julia.
Независимо от того, привыкли вы к Python или нет, Джулия из MIT Labs может стать вашим лучшим выбором на будущее.