Почувствуй прелесть Джулии — язык для искусственного интеллекта

Julia
Почувствуй прелесть Джулии — язык для искусственного интеллекта

Почему выбирают Юлию?

Когда речь заходит о науке о данных, машинном обучении, глубоком обучении, искусственном интеллекте и т. д., первым инструментом, который приходит на ум, должен быть 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 может стать вашим лучшим выбором на будущее.