QA2TJZRA7RYN5UMRDLXWASQBU7YXV63R2A33EVJME6FV4S67WY3AC
X54TLSYE7DYWGLQUI7AIZOABUCQ7WTHFC6G62UBA7RJZK4AYOJGAC
YODTMMPTZOUTK2OQWHDJB6D3QXZ2FJFYH2XPICCOITCK54EARC2AC
PHGT4YMBYADGJLIVX2OOIY4YV7SHLIGPDXM6XXSQ7I4MH2SQURIAC
G4IN2F2T2ZENRYWXXMEB73IUCTZ4SILAII2NVECLY2UEGKP44XYQC
NV7FXZ5QETWHE7EQHET5ZZUKH4UIAIRGQ42MR2IT5JCZDPRNEZRQC
EDYR5C55YKPEMJOS4O6YEUK5JYUWSX4NTPQGG4GLH5QL2O62GTPQC
BOPNWZL4RWF4UGC2LUEVONNQFSKYJ2Q5W747GH3UURZLBJFFEBUQC
ETOIK7VEDSRQX6JISLV7WWAW2O7UTBWV6MHTRKVTHARXOD77MX2QC
FY7CEMM2ZSPOL62BX2JR3VBGUTAWEPIJ26AUT4U3GHTWWCAZZY2AC
27HKDBYTNASZMCIKAVZ4TMPZD35PAC7LMMIEHKY6MHJMZZ4AFUPAC
RQ56K2G4ZCSZLOXCAPZFWAPW7PC7KTGJXUYD6MFOK4P6DQ2JYKGAC
NMQCXLNGPIKUKMNKEIVUBYUNJQDM63IVKRVMQHVV5TLH6OBNF3IAC
3FAESP6NBZJHKN6VSGENUMZXPID6O5CGNQ3NHJC5Z3YXTAXJVWVAC
SMODB47PJBBRRAXJNDWX4LTSNUW3BUILYGSQQ2ZKLYGT6OLO722AC
RBXUHIO2WALXMYGFRWNDLVHFH4OOMCODI3K4HKZNWGWUX6INB6LAC
ZGLDIQ4GDQVKVUVLFUXGYD347222QA7633TVV4BUHCSHF7DAJ4DAC
PQ6OQCBQUJMAGTITCWSBFIKCGW3BO7ZOBQ2AB7DQOIUNZH2KICYAC
QPBH7QWC56HIYUJCCHKDNBN2D346UN3IOXDCIKSAATLIATLSW3YQC
E3Y55MPRKKDPTGI56RSA7YCGB33NSZYKHGCVHEUKRM2KJ2RNM5IQC
4BTZNCRM7R6SZPE5W7UENKS2LNXXRWVXGGZAM7QOWDIPEGW3LQ6AC
MMG2PLXK54U7GEVNK65SALH3BZEKWTP6ZSNBELMO3CZJP25MGZ5QC
U46LDPL7W76Z62KUTGA6QNB27C7HGBFUXT6E7V5X4ACTDUBTKAKAC
JYCKLP2EZJHX7QWMGN6TZZLRXOG7A4LUO64X2ORWDMSJX7LM7XIQC
L7G33K4C6EA6SZ6M2QN2KAXCSOQRP3VFCZNIC5LO4MXXKAB5EYHAC
WOSKMRI4SBMMYLPCOGUGEYM6BUV6A6K735YWTM3WN4GZFGBKGHBQC
2UBDFCJH2BG6U6SY2YDJ7QK4JOLUJAHOYZS3YRQ7E7U4UGP4YR5QC
2O6SHIVYVHLSJNQ6WXFV2DSI6WPQWTXS3X6YY4V5JO3XEOEURUHQC
YXAKJSDTRZXBQLFL6VLB7QTLA2QAXZNS6CY3K4XAKFGCL2XM6EOQC
OFTU77S5FEE5SWAV7G4OWAQ7GY6LOEY65ZTMJCDMPMJGB7TWDIOQC
MIT License
Copyright (c) 2023 David Cary <cdecary@gmail.com> and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Train.jl
export train #beware Flux.train! is not Skraak.train
import Base: length, getindex
import MLBase
using CUDA, Dates, Images, Flux, Glob, JLD2, Noise
using Random: shuffle!, seed!
using Metalhead: ResNet
#=
function train(
model_name::String,
train_epochs::Int64,
images::Vector{String},
pretrain::Model=true,
train_test_split::Float64 = 0.8,
batch_size::Int64 = 64,
)
Note:
Dont forget temp env, julia -t 4
Assumes 224x224 pixel RGB images as png's
Saves jld2's in current directory
Use like:
using Skraak, Glob
images = glob("kiwi_set*/*/[N,K]/*.png") #11699814-element Vector{String}
model = "/media/david/SSD2/PrimaryDataset/model_K1-9_original_set_CPU_epoch-7-0.9924-2024-03-05.jld2"
train("K1-10_total_set_no_augumentation", 2, images, model, 0.97, 64)
images = glob("*/[D,F,M,N]/*.png") #from SSD2/Clips
model = "/media/david/SSD2/PrimaryDataset/model_K1-5_CPU_epoch-6-0.9795-2023-12-16.jld2"
train("DFMN1-5", 20, images, model)
=#
const LABELTOINDEX::Dict{String,Int32} = Dict()
Model = Union{Bool,String}
function train(
model_name::String,
train_epochs::Int64,
images::Vector{String}, #glob_pattern::String = "*/*.png"
pretrain::Model = true,
train_test_split::Float64 = 0.8,
batch_size::Int64 = 64,
)
epochs = 1:train_epochs
#images = glob(glob_pattern) #|> shuffle! |> x -> x[1:640]
@assert !isempty(images) "No png images found"
@info "$(length(images)) images in dataset"
label_to_index = labels_to_dict(images)
register_label_to_index!(label_to_index)
@info "Text labels translate to: " label_to_index
classes = length(label_to_index)
@assert classes >= 2 "At least 2 label classes are required, for example: kiwi, not_kiwi"
@info "$classes classes in dataset"
@info "Device: $device"
ceiling = seil(length(images), batch_size)
train_test_index = train_test_idx(ceiling, batch_size, train_test_split)
train, train_sample, test = process_data(images, train_test_index, ceiling, batch_size)
@info "Made data loaders"
model = load_model(pretrain, classes)
@info "Loaded model"
opt = Flux.setup(Flux.Optimisers.Adam(1e-5), model)
@info "Setup optimiser"
@info "Training for $epochs epochs: " now()
training_loop!(
model,
opt,
train,
train_sample,
test,
epochs,
model_name,
classes,
label_to_index,
)
@info "Finished $(last(epochs)) epochs: " now()
end
struct ImageContainer{T<:Vector}
img::T
end
struct ValidationImageContainer{T<:Vector}
img::T
end
Container = Union{ImageContainer,ValidationImageContainer}
function seil(n::Int, batch_size::Int)
return n ÷ batch_size * batch_size
end
function train_test_idx(ceiling::Int, batch_size::Int, train_test_split::Float64)::Int
t =
#! format: off
ceiling ÷ batch_size * train_test_split |>
round |>
x -> x * batch_size |>
x -> convert(Int, x)
#! format: on
end
function labels_to_dict(list::Vector{String})::Dict{String,Int32}
l =
#! format: off
map(x -> split(x, "/")[end-1], list) |>
unique |>
sort |>
x -> zip(x, 1:length(x)) |>
Dict
#! format: on
return l
end
"""
register_label_to_index!(label_to_index::Dict{String,Int32})
This will replace the content of the global variable LABELTOINDEX
with the content intended by the caller.
Thanks algunion
https://discourse.julialang.org/t/dataloader-scope-troubles/105207/4
"""
function register_label_to_index!(label_to_index::Dict{String,Int32})
empty!(LABELTOINDEX)
merge!(LABELTOINDEX, label_to_index)
end
device = CUDA.functional() ? gpu : cpu
function process_data(array_of_file_names, train_test_index, ceiling, batch_size)
seed!(1234)
images = shuffle!(array_of_file_names)
train =
ImageContainer(images[1:train_test_index]) |> x -> make_dataloader(x, batch_size)
train_sample =
ValidationImageContainer(images[1:(ceiling-train_test_index)]) |>
x -> make_dataloader(x, batch_size)
test =
ValidationImageContainer(images[train_test_index+1:ceiling]) |>
x -> make_dataloader(x, batch_size)
return train, train_sample, test
end
length(data::ImageContainer) = length(data.img)
length(data::ValidationImageContainer) = length(data.img)
function getindex(data::ImageContainer{Vector{String}}, index::Int)
path = data.img[index]
img =
#! format: off
Images.load(path) |>
#x -> Images.imresize(x, 224, 224) |>
#x -> Images.RGB.(x) |>
x -> Noise.add_gauss(x, (rand() * 0.2)) |>
x -> apply_mask!(x, 3, 3, 12) |>
x -> collect(channelview(float32.(x))) |>
x -> permutedims(x, (3, 2, 1))
#! format: on
y = LABELTOINDEX[(split(path, "/")[end-1])]
return img, y
end
function getindex(data::ValidationImageContainer{Vector{String}}, index::Int)
path = data.img[index]
img =
#! format: off
Images.load(path) |>
#x -> Images.imresize(x, 224, 224) |>
#x -> Images.RGB.(x) |>
x -> collect(channelview(float32.(x))) |>
x -> permutedims(x, (3, 2, 1))
#! format: on
y = LABELTOINDEX[(split(path, "/")[end-1])]
return img, y
end
# assumes 224px square images
function apply_mask!(
img::Array{RGB{N0f8},2},
max_number::Int = 3,
min_size::Int = 3,
max_size::Int = 22,
)
# horizontal
for range in get_random_ranges(max_number, min_size, max_size)
img[range, :] .= RGB{N0f8}(0.7, 0.7, 0.7)
end
# vertical
for range in get_random_ranges(max_number, min_size, max_size)
img[:, range] .= RGB{N0f8}(0.7, 0.7, 0.7)
end
return img
end
# assumes 224px square images
function get_random_ranges(max_number::Int, min_size::Int, max_size::Int)
number = rand(0:max_number)
ranges = []
while length(ranges) < number
start = rand(1:224)
size = rand(min_size:max_size)
if start + size > 224
continue
end
push!(ranges, start:start+size)
end
return ranges
end
function make_dataloader(container::Container, batch_size::Int)
data =
Flux.DataLoader(container; batchsize = batch_size, collate = true, parallel = true)
device == gpu ? data = CuIterator(data) : nothing
return data
end
# see load_model() from predict, and below
function load_model(pretrain::Bool, classes::Int64)
fst = Metalhead.ResNet(18, pretrain = pretrain).layers
lst = Flux.Chain(AdaptiveMeanPool((1, 1)), Flux.flatten, Dense(512 => classes))
model = Flux.Chain(fst[1], lst) |> device
return model
end
#If model classes == desired classes I don't empty the last layer
#That means that I can just train from where I left off for new data, DFMN model
#Could be a gotcha if I want to train a different 4 class model, no need for a switch just yet
function load_model(model_path::String, classes::Int64)
model_state = JLD2.load(model_path, "model_state")
model_classes = length(model_state[1][2][1][3][2])
f = Metalhead.ResNet(18, pretrain = false).layers
l = Flux.Chain(AdaptiveMeanPool((1, 1)), Flux.flatten, Dense(512 => model_classes))
m = Flux.Chain(f[1], l)
Flux.loadmodel!(m, model_state)
if classes == model_classes
model = m |> device
else
fst = m.layers
lst = Flux.Chain(AdaptiveMeanPool((1, 1)), Flux.flatten, Dense(512 => classes))
model = Flux.Chain(fst[1], lst) |> device
end
return model
end
function evaluate(m, d, c)
good = 0
count = 0
pred = Int64[]
actual = Int64[]
for (x, y) in d
p = Flux.onecold(m(x))
good += sum(p .== y)
count += length(y)
append!(pred, p)
append!(actual, y)
end
accuracy = round(good / count, digits = 4)
confusion_matrix = MLBase.confusmat(c, actual, pred)
#freqtable(DataFrame(targets = actual, predicts = pred), :targets, :predicts)
#roc=MLBase.roc(actual, pred, 100)
#f1=MLBase.f1score(roc)
return accuracy, confusion_matrix #, roc, f1
end
function train_epoch!(model; opt, train, classes)
Flux.train!(model, train, opt) do m, x, y
Flux.Losses.logitcrossentropy(m(x), Flux.onehotbatch(y, 1:classes))
end
end
function dict_to_text_file(dict, model_name)
text = ""
for (key, value) in dict
text = text * "$(key) => $(value)\n"
end
open("labels_$(model_name)-$(today()).txt", "w") do file
write(file, text)
end
@info "Saved labels to file for future reference"
end
function training_loop!(
model,
opt,
train,
train_sample,
test,
epochs::UnitRange{Int64},
model_name::String,
classes,
label_to_index,
)
@time eval, vcm = evaluate(model, test, classes)
@info "warm up accuracy" accuracy = eval
@info "warm up confusion matrix" vcm
a = 0
for epoch in epochs
println("")
@info "Starting Epoch: $epoch"
epoch == 1 && dict_to_text_file(label_to_index, model_name)
@time train_epoch!(model; opt, train, classes)
@time train_accuracy, train_confusion_matrix =
evaluate(model, train_sample, classes)
@info "Epoch: $epoch"
@info "train" accuracy = train_accuracy
@info "train" train_confusion_matrix
@time test_accuracy, test_confusion_matrix = evaluate(model, test, classes)
@info "test" accuracy = test_accuracy
@info "test" test_confusion_matrix
# number kiwi guessed right, assumes kiwi=1, not=2 (alphabetical)
#test_confusion_matrix[1,1] > a && begin
#a = test_confusion_matrix[1,1]
let _model = cpu(model)
jldsave(
"/media/david/SSD2/model_$(model_name)_CPU_epoch-$epoch-$test_accuracy-$(today()).jld2";
model_state = Flux.state(_model),
)
@info "Saved a best_model"
end
#end
end
end
# Predict.jl
using WAV,
DSP, Images, ThreadsX, Dates, DataFrames, CSV, Flux, CUDA, Metalhead, JLD2, FLAC, Glob
import Base: length, getindex
"""
predict(glob_pattern::String, model::String)
This function takes a glob pattern for folders (or a vector of folders) to run over, and a model path. It saves results in a csv in each folder, similar to opensoundscape
Args:
• glob pattern (folder/) or a vector of folders
• model path
Returns: Nothing - This function saves csv files.
I use this function to find kiwi from new data gathered on a trip. And to predict D/F/M/N for images clipped from primary detections.
It works on both audio (wav or flac) and png images.
Note:
From Pomona-3/Pomona-3/
Use like:
using Skraak
glob_pattern = "*/*/"
model = "/media/david/SSD2/PrimaryDataset/model_K1-9_original_set_CPU_epoch-7-0.9924-2024-03-05.jld2"
glob_pattern = "Clips_2024-10-21/"
model = "/media/david/SSD1/Clips/model_DFMN1-5_CPU_epoch-18-0.9132-2024-01-29.jld2"
predict(glob_pattern, model)
"""
function predict(glob_pattern::String, model::String)
model = load_model_pred(model) |> device
folders = glob(glob_pattern)
@info "Folders: $folders"
for folder in folders
@info "Working on: $folder"
predict_folder(folder, model)
end
end
function predict(folders::Vector{String}, model::String)
model = load_model_pred(model) |> device
@info "Folders: $folders"
for folder in folders
@info "Working on: $folder"
predict_folder(folder, model)
end
end
#~~~~~ The guts ~~~~~#
struct PredictImageContainer{T<:Vector}
img::T
end
length(data::PredictImageContainer) = length(data.img)
function getindex(data::PredictImageContainer{Vector{String}}, idx::Int)
path = data.img[idx]
img =
#! format: off
Images.load(path) |>
x -> Images.imresize(x, 224, 224)|>
x -> Images.RGB.(x) |>
x -> collect(channelview(float32.(x))) |>
x -> permutedims(x, (3, 2, 1))
#! format: on
return img, path
end
function predict_image_folder(png_files::Vector{String}, model, folder::String)
l = length(png_files)
@assert (l > 0) "No png files present in $folder"
@info "$(l) png_files in $folder"
save_path = "$folder/preds-$(today()).csv"
loader = png_loader(png_files)
@time preds, files = predict_pngs(model, loader)
f = split.(files, "/") |> x -> last.(x)
df = DataFrame(file = f, label = preds)
CSV.write("$save_path", df)
end
function png_loader(png_files::Vector{String})
loader = Flux.DataLoader(
PredictImageContainer(png_files);
batchsize = 64,
collate = true,
parallel = true,
)
device == gpu ? loader = CuIterator(loader) : nothing
return loader
end
function predict_pngs(m, d)
@info "Predicting..."
pred = []
path = []
for (x, pth) in d
p = Flux.onecold(m(x))
append!(pred, p)
append!(path, pth)
end
return pred, path
end
# Predict from audio files
function predict_audio_folder(audio_files::Vector{String}, model, folder::String)
l = length(audio_files)
@assert (l > 0) "No wav or flac audio files present in $folder"
@info "$(l) audio_files in $folder"
df = DataFrame(
file = String[],
start_time = Float64[],
end_time = Float64[],
label = Int[],
)
save_path = "$folder/preds-$(today()).csv"
CSV.write("$save_path", df)
for file in audio_files
df = predict_audio_file(file, model)
CSV.write("$save_path", df, append = true)
end
end
function predict_audio_file(file::String, model)
#check form of opensoundscape preds.csv and needed by my make_clips
@info "File: $file"
@time data = audio_loader(file)
pred = []
time = []
@time for (x, t) in data
p = Flux.onecold(model(x))
append!(pred, p)
append!(time, t)
end
f = (repeat(["$file"], length(time)))
df = DataFrame(
:file => f,
:start_time => first.(time),
:end_time => last.(time),
:label => pred,
)
sort!(df)
return df
end
function audio_loader(file::String, increment::Int = 5, divisor::Int = 2)
raw_images, n_samples = get_images_from_audio(file::String, increment, divisor)
images = reshape_images(raw_images, n_samples)
start_time = 0:(increment/divisor):(n_samples-1)*(increment/divisor)
end_time = increment:(increment/divisor):(n_samples+1)*(increment/divisor)
time = collect(zip(start_time, end_time))
loader = Flux.DataLoader((images, time), batchsize = n_samples, shuffle = false)
device == gpu ? loader = CuIterator(loader) : nothing #check this works with gpu
return loader
end
function reshape_images(raw_images, n_samples)
images =
#! format: off
hcat(raw_images...) |>
x -> reshape(x, (224, 224, 3, n_samples))
#! format: on
return images
end
# need to change divisor to a overlap fraction, chech interaction with audioloader()
# if divisor is 0, then no overlap atm
function get_images_from_audio(file::String, increment::Int = 5, divisor::Int = 2) #5s sample, 2.5s hop
signal, freq = load_audio_file(file)
if freq > 16000
signal, freq = resample_to_16000hz(signal, freq)
end
f = convert(Int, freq)
inc = increment * f
#hop = f * increment ÷ divisor #need guarunteed Int, maybe not anymore, refactor
hop = 0 #f * increment / divisor |> x -> x == Inf ? 0 : trunc(Int, x)
split_signal = DSP.arraysplit(signal[:, 1], inc, hop)
raw_images = ThreadsX.map(x -> get_image_from_sample(x, f), split_signal)
n_samples = length(raw_images)
return raw_images, n_samples
end
function load_audio_file(file::String)
ext = split(file, ".")[end]
@assert ext in ["WAV", "wav", "flac"] "Unsupported audio file type, requires wav or flac."
if ext in ["WAV", "wav"]
signal, freq = WAV.wavread(file)
else
signal, freq = load(file)
end
@assert !isempty(signal[:, 1]) "$file seems to be empty, could it be corrupted?\nYou could delete it, or replace it with a known\ngood version from SD card or backup."
return signal, freq
end
function resample_to_16000hz(signal, freq)
signal = DSP.resample(signal, 16000.0f0 / freq; dims = 1)
freq = 16000
return signal, freq
end
############### PYTHON Opensoundscape ################
#=
# Dont forget conda activate opensoundscape
# Dont forget to modify file names and glob pattern
# Run script in Pomona-2, hard code trip date in the glob
# python /media/david/USB/Skraak/src/predict.py
from opensoundscape.torch.models.cnn import load_model
import opensoundscape
import torch
from pathlib import Path
import numpy as np
import pandas as pd
from glob import glob
import os
from datetime import datetime
model = load_model('/home/david/best.model0')
# folders = glob('./*/2023-?????/')
# folders = glob('./*/*/2024-05-0?')
folders = glob('./*/2024-10-18/')
for folder in folders:
os.chdir(folder)
print(folder, ' start: ', datetime.now())
# Beware, secretary island files are .wav
field_recordings = glob('./*.[W,w][A,a][V,v]')
scores, preds, unsafe = model.predict(
field_recordings,
binary_preds = 'single_target',
overlap_fraction = 0.5,
batch_size = 128,
num_workers = 12)
scores.to_csv("scores-2024-10-21.csv")
preds.to_csv("preds-2024-10-21.csv")
os.chdir('../..') # Be careful this matches the glob on line 284
print(folder, ' done: ', datetime.now())
print()
print()
=#
#=Kahurangi
folders = glob('./*/')
for folder in folders:
os.chdir(folder)
print(folder, ' start: ', datetime.now())
# Beware, secretary island files are .wav
field_recordings = glob('./*.[W,w][A,a][V,v]')
scores, preds, unsafe = model.predict(
field_recordings,
binary_preds = 'single_target',
overlap_fraction = 0.5,
batch_size = 128,
num_workers = 12)
scores.to_csv("scores-2024-10-21.csv")
preds.to_csv("preds-2024-10-21.csv")
os.chdir('./..') # Be careful this matches the glob on line 284
print(folder, ' done: ', datetime.now())
print()
print()
=#
# Python 3.8.12, opensoundscape 0.7.1
function resample_to_8000hz(signal, freq)
signal = DSP.resample(signal, 8000.0f0 / freq; dims = 1)
freq = 8000
return signal, freq
end
function get_image_for_inference(sample, f)
image =
#! format: off
get_image_from_sample(sample, f) |>
# x -> collect(channelview(float32.(x))) |>
x -> permutedims(x, (3, 2, 1))
#! format: on
return image
end
=#
#= not needed
# Start time and end time for each 5s audio clip, in seconds relative to the start of the file.
# see load_model() from train, different input types
function load_model_pred(model_path::String)
model_state = JLD2.load(model_path, "model_state")
model_classes = length(model_state[1][2][1][3][2])
f = Metalhead.ResNet(18, pretrain = false).layers
l = Flux.Chain(AdaptiveMeanPool((1, 1)), Flux.flatten, Dense(512 => model_classes))
model = Flux.Chain(f[1], l)
Flux.loadmodel!(model, model_state)
return model
end
#=
function load_bson(model_path::String)
BSON.@load model_path model
end
=#
function predict_folder(folder::String, model)
wav = glob("$folder/*.[W,w][A,a][V,v]")
flac = glob("$folder/*.flac")
audio_files = vcat(wav, flac) #if wav and flac both present will predict on all
png_files = glob("$folder/*.png")
#it will predict on images when both images and audio present
if isempty(png_files)
length(audio_files) > 0 ? predict_audio_folder(audio_files, model, folder) :
@info "No png, flac, wav, WAV files present in $folder"
else
predict_image_folder(png_files, model, folder)
end
end
device = CUDA.functional() ? gpu : cpu
# Predict from png images
@info "Model classes: $model_classes"
julia -t 4
Dont forget temp environment: ] activate --temp
export predict
export get_images_from_audio
function resample_to_16000hz(signal, freq)
signal = DSP.resample(signal, 16000.0f0 / freq; dims = 1)
freq = 16000
return signal, freq
end
function resample_to_8000hz(signal, freq)
signal = DSP.resample(signal, 8000.0f0 / freq; dims = 1)
freq = 8000
return signal, freq
end
file
[D, F, M, N]/C05-2023-04-15-20230219_223000-380-470.png
This function takes the csv output from my hand classification and ouputs a df, and csv for insertion into AudioData.duckdb using the duckdb cli or using DFto.audiodata_db()
assumes run from Clips_xxxx-xx-xx folder and that "actual.csv" present if not specified.
returns a dataframe
using CSV, DataFrames, DataFramesMeta
"""
"""
aggregate_labels(actual="actual.csv", outfile="labels.csv")
file
[D, F, M, N]/C05-2023-04-15-20230219_223000-380-470.png
This function takes the csv output from my hand classification and ouputs a df, and csv for insertion into AudioData.duckdb using the duckdb cli or using DFto.audiodata_db()
assumes run from Clips_xxxx-xx-xx folder and that "actual.csv" present if not specified.
returns a dataframe
using CSV, DataFrames, DataFramesMeta
"""
make_clips(preds_path::String, dawn_dusk_dict::Dict{Dates.Date, Tuple{Dates.DateTime, Dates.DateTime}} = construct_dawn_dusk_dict("/media/david/SSD1/dawn_dusk.csv"))
This function takes a preds.csv files and generates
file names, wav's, spectrograms etc to be reviewed.
it calls night() and may call construct_dawn_dusk_dict() unless the dict is globally defined and passed in
It should be run from Pomona-1/, Pomona-2/ or Pomona-3/, assumes it is, it uses the path
It saves wav and png files to current working directory, ie Pomona-3
need to use a try/catch because the 2 assert functions thow an error to short circuit the function
=#
"""
make_clips(preds_path::String, dawn_dusk_dict::Dict{Dates.Date, Tuple{Dates.DateTime, Dates.DateTime}} = construct_dawn_dusk_dict("/media/david/SSD1/dawn_dusk.csv"))
This function takes a preds.csv files and generates
file names, wav's, spectrograms etc to be reviewed.
it calls night() and may call construct_dawn_dusk_dict() unless the dict is globally defined and passed in
It should be run from Pomona-1/, Pomona-2/ or Pomona-3/, assumes it is, it uses the path
It saves wav and png files to current working directory, ie Pomona-3
need to use a try/catch because the 2 assert functions thow an error to short circuit the function
"""
DataFrame(CSV.File(preds_path)) |>
x -> assert_not_empty(x, preds_path) |>
x -> rename_column!(x, "1.0", "label") |> #can remove now, needs to be label
x -> assert_detections_present(x, label, location, trip_date) |>
x -> filter_positives!(x, label) |>
DataFrames.DataFrame(CSV.File(preds_path)) |>
x -> Skraak.assert_not_empty(x, preds_path) |>
x -> Skraak.rename_column!(x, "1.0", "label") |> #can remove now, needs to be label
x -> Skraak.assert_detections_present(x, label, location, trip_date) |>
x -> Skraak.filter_positives!(x, label) |>
signal, freq = wavread("$location/$trip_date/$(file_name).$(extension)")
##signal, freq = wavread("$location/$h/$trip_date/$(file_name).$(extension)")
signal, freq = WAV.wavread("$location/$trip_date/$(file_name).$(extension)")
##signal, freq = WAV.wavread("$location/$h/$trip_date/$(file_name).$(extension)")
df=DataFrames.DataFrame(dict)
df=CSV.File("dawn_dusk.csv") |> DataFrame
open("dict.jl", "w") do file
write(file, "const dddict = Dict(")
for row in eachrow(df)
line="\tDates.Date(\"$(row.Date)\") =>
(Dates.DateTime(\"$(row.Dawn)\"), Dates.DateTime(\"$(row.Dusk)\")),\n"
write(file, line)
end
write(file, ")")
end
using CSV, DataFrames
=#
I use this to decide if a file with a local time encoded name was recorded at night
dict = construct_dawn_dusk_dict("/Volumes/SSD1/dawn_dusk.csv")
using CSV, DataFrames
I use this to decide if a file with a local time encoded name was recorded at nigh
[[deps.Accessors]]
deps = ["CompositionsBase", "ConstructionBase", "InverseFunctions", "LinearAlgebra", "MacroTools", "Markdown"]
git-tree-sha1 = "b392ede862e506d451fc1616e79aa6f4c673dab8"
uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
version = "0.1.38"
[deps.Accessors.extensions]
AccessorsAxisKeysExt = "AxisKeys"
AccessorsDatesExt = "Dates"
AccessorsIntervalSetsExt = "IntervalSets"
AccessorsStaticArraysExt = "StaticArrays"
AccessorsStructArraysExt = "StructArrays"
AccessorsTestExt = "Test"
AccessorsUnitfulExt = "Unitful"
[deps.Accessors.weakdeps]
AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "50c3c56a52972d78e8be9fd135bfb91c9574c140"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "4.1.1"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"
[[deps.BFloat16s]]
deps = ["LinearAlgebra", "Printf", "Random", "Test"]
git-tree-sha1 = "2c7cc21e8678eff479978a0a2ef5ce2f51b63dff"
uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
version = "0.5.0"
[[deps.BSON]]
git-tree-sha1 = "4c3e506685c527ac6a54ccc0c8c76fd6f91b42fb"
uuid = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
version = "0.3.9"
[[deps.BangBang]]
deps = ["Accessors", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires"]
git-tree-sha1 = "e2144b631226d9eeab2d746ca8880b7ccff504ae"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.4.3"
[deps.BangBang.extensions]
BangBangChainRulesCoreExt = "ChainRulesCore"
BangBangDataFramesExt = "DataFrames"
BangBangStaticArraysExt = "StaticArrays"
BangBangStructArraysExt = "StructArrays"
BangBangTablesExt = "Tables"
BangBangTypedTablesExt = "TypedTables"
[deps.BangBang.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
[[deps.CUDA]]
deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "Crayons", "DataFrames", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LLVMLoopInfo", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "NVTX", "Preferences", "PrettyTables", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "StaticArrays", "Statistics", "demumble_jll"]
git-tree-sha1 = "e0725a467822697171af4dae15cec10b4fc19053"
uuid = "052768ef-5323-5732-b1bb-66c8b64840ba"
version = "5.5.2"
[deps.CUDA.extensions]
ChainRulesCoreExt = "ChainRulesCore"
EnzymeCoreExt = "EnzymeCore"
SpecialFunctionsExt = "SpecialFunctions"
[deps.CUDA.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
[[deps.CUDA_Driver_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ccd1e54610c222fadfd4737dac66bff786f63656"
uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc"
version = "0.10.3+0"
[[deps.CUDA_Runtime_Discovery]]
deps = ["Libdl"]
git-tree-sha1 = "33576c7c1b2500f8e7e6baa082e04563203b3a45"
uuid = "1af6417a-86b4-443c-805f-a4643ffb695f"
version = "0.3.5"
[[deps.CUDA_Runtime_jll]]
deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "e43727b237b2879a34391eeb81887699a26f8f2f"
uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2"
version = "0.15.3+0"
[[deps.CUDNN_jll]]
deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "9851af16a2f357a793daa0f13634c82bc7e40419"
uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645"
version = "9.4.0+0"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "SparseInverseSubset", "Statistics", "StructArrays", "SuiteSparse"]
git-tree-sha1 = "be227d253d132a6d57f9ccf5f67c0fb6488afd87"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.71.0"
[[deps.CommonSubexpressions]]
deps = ["MacroTools"]
git-tree-sha1 = "cda2cfaebb4be89c9084adaca7dd7333369715c5"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.1"
[[deps.CompositionsBase]]
git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.2"
weakdeps = ["InverseFunctions"]
[[deps.DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"
[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"
[[deps.DiffResults]]
deps = ["StaticArraysCore"]
git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.1.0"
[[deps.DiffRules]]
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.15.1"
[[deps.FLoops]]
deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"]
git-tree-sha1 = "0a2e5873e9a5f54abb06418d57a8df689336a660"
uuid = "cc61a311-1640-44b5-9fba-1b764f453329"
version = "0.2.2"
[[deps.FLoopsBase]]
deps = ["ContextVariablesX"]
git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7"
uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6"
version = "0.1.1"
[[deps.FillArrays]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.13.0"
[deps.FillArrays.extensions]
FillArraysPDMatsExt = "PDMats"
FillArraysSparseArraysExt = "SparseArrays"
FillArraysStatisticsExt = "Statistics"
[deps.FillArrays.weakdeps]
PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
[[deps.Flux]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Functors", "LinearAlgebra", "MLDataDevices", "MLUtils", "MacroTools", "NNlib", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "Setfield", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote"]
git-tree-sha1 = "df520a0727f843576801a0294f5be1a94be28e23"
uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c"
version = "0.14.25"
[deps.Flux.extensions]
FluxAMDGPUExt = "AMDGPU"
FluxCUDAExt = "CUDA"
FluxCUDAcuDNNExt = ["CUDA", "cuDNN"]
FluxEnzymeExt = "Enzyme"
FluxMPIExt = "MPI"
FluxMPINCCLExt = ["CUDA", "MPI", "NCCL"]
[deps.Flux.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9"
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
NCCL = "3fe64909-d7a1-4096-9b7d-7a0f12cf0f6b"
cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
git-tree-sha1 = "a2df1b776752e3f344e5116c06d75a10436ab853"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.38"
weakdeps = ["StaticArrays"]
[deps.ForwardDiff.extensions]
ForwardDiffStaticArraysExt = "StaticArrays"
[[deps.Functors]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "64d8e93700c7a3f28f717d265382d52fac9fa1c1"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.4.12"
[[deps.GPUArrays]]
deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"]
git-tree-sha1 = "62ee71528cca49be797076a76bdc654a170a523e"
uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
version = "10.3.1"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950"
uuid = "46192b85-c4d5-4398-a991-12ede77f4527"
version = "0.1.6"
[[deps.GPUCompiler]]
deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "PrecompileTools", "Preferences", "Scratch", "Serialization", "TOML", "TimerOutputs", "UUIDs"]
git-tree-sha1 = "1d6f290a5eb1201cd63574fbc4440c788d5cb38f"
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
version = "0.27.8"
[[deps.IRTools]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "950c3717af761bc3ff906c2e8e52bd83390b6ec2"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.14"
[[deps.InverseFunctions]]
git-tree-sha1 = "a779299d77cd080bf77b97535acecd73e1c5e5cb"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.17"
weakdeps = ["Dates", "Test"]
[deps.InverseFunctions.extensions]
InverseFunctionsDatesExt = "Dates"
InverseFunctionsTestExt = "Test"
[[deps.JuliaNVTXCallbacks_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "af433a10f3942e882d3c671aacb203e006a5808f"
uuid = "9c1d0b0a-7046-5b2e-a33f-ea22f176ac7e"
version = "0.2.1+0"
[[deps.JuliaVariables]]
deps = ["MLStyle", "NameResolution"]
git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70"
uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec"
version = "0.2.4"
[[deps.KernelAbstractions]]
deps = ["Adapt", "Atomix", "InteractiveUtils", "MacroTools", "PrecompileTools", "Requires", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "e73a077abc7fe798fe940deabe30ef6c66bdde52"
uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
version = "0.9.29"
[deps.KernelAbstractions.extensions]
EnzymeExt = "EnzymeCore"
LinearAlgebraExt = "LinearAlgebra"
SparseArraysExt = "SparseArrays"
[deps.KernelAbstractions.weakdeps]
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.LLVM]]
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Preferences", "Printf", "Unicode"]
git-tree-sha1 = "d422dfd9707bec6617335dc2ea3c5172a87d5908"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "9.1.3"
weakdeps = ["BFloat16s"]
[deps.LLVM.extensions]
BFloat16sExt = "BFloat16s"
[[deps.LLVMExtra_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "05a8bd5a42309a9ec82f700876903abce1017dd3"
uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab"
version = "0.0.34+0"
[[deps.LLVMLoopInfo]]
git-tree-sha1 = "2e5c102cfc41f48ae4740c7eca7743cc7e7b75ea"
uuid = "8b046642-f1f6-4319-8d3c-209ddc03c586"
version = "1.0.0"
[[deps.MLBase]]
deps = ["IterTools", "Random", "Reexport", "StatsBase"]
git-tree-sha1 = "ac79beff4257e6e80004d5aee25ffeee79d91263"
uuid = "f0e99cf1-93fa-52ec-9ecc-5026115318e0"
version = "0.9.2"
[[deps.MLDataDevices]]
deps = ["Adapt", "Compat", "Functors", "Preferences", "Random"]
git-tree-sha1 = "d0666f5a9294484110e2bfc12e07cff5a434488d"
uuid = "7e8f7934-dd98-4c1a-8fe8-92b47a384d40"
version = "1.5.0"
[deps.MLDataDevices.extensions]
MLDataDevicesAMDGPUExt = "AMDGPU"
MLDataDevicesCUDAExt = "CUDA"
MLDataDevicesChainRulesCoreExt = "ChainRulesCore"
MLDataDevicesFillArraysExt = "FillArrays"
MLDataDevicesGPUArraysExt = "GPUArrays"
MLDataDevicesMLUtilsExt = "MLUtils"
MLDataDevicesMetalExt = ["GPUArrays", "Metal"]
MLDataDevicesReactantExt = "Reactant"
MLDataDevicesRecursiveArrayToolsExt = "RecursiveArrayTools"
MLDataDevicesReverseDiffExt = "ReverseDiff"
MLDataDevicesSparseArraysExt = "SparseArrays"
MLDataDevicesTrackerExt = "Tracker"
MLDataDevicesZygoteExt = "Zygote"
MLDataDevicescuDNNExt = ["CUDA", "cuDNN"]
MLDataDevicesoneAPIExt = ["GPUArrays", "oneAPI"]
[deps.MLDataDevices.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
GPUArrays = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54"
Metal = "dde4c033-4e86-420c-a63e-0dd931031962"
Reactant = "3c362404-f566-11ee-1572-e11a4b42c853"
RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
oneAPI = "8f75cd03-7ff8-4ecb-9b8f-daf728133b1b"
[[deps.MLStyle]]
git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
version = "0.4.17"
[[deps.MLUtils]]
deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"]
git-tree-sha1 = "b45738c2e3d0d402dffa32b2c1654759a2ac35a4"
uuid = "f1d291b0-491e-4a28-83b9-f70985020b54"
version = "0.4.4"
[[deps.Metalhead]]
deps = ["Artifacts", "BSON", "ChainRulesCore", "Flux", "Functors", "JLD2", "LazyArtifacts", "MLUtils", "NNlib", "PartialFunctions", "Random", "Statistics"]
git-tree-sha1 = "aef476e4958303f5ea9e1deb81a1ba2f510d4e11"
uuid = "dbeba491-748d-5e0e-a39e-b530a07fa0cc"
version = "0.9.4"
weakdeps = ["CUDA"]
[deps.Metalhead.extensions]
MetalheadCUDAExt = "CUDA"
[[deps.MicroCollections]]
deps = ["Accessors", "BangBang", "InitialValues"]
git-tree-sha1 = "44d32db644e84c75dab479f1bc15ee76a1a3618f"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.2.0"
[[deps.NNlib]]
deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "da09a1e112fd75f9af2a5229323f01b56ec96a4c"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.9.24"
[deps.NNlib.extensions]
NNlibAMDGPUExt = "AMDGPU"
NNlibCUDACUDNNExt = ["CUDA", "cuDNN"]
NNlibCUDAExt = "CUDA"
NNlibEnzymeCoreExt = "EnzymeCore"
NNlibFFTWExt = "FFTW"
NNlibForwardDiffExt = "ForwardDiff"
[deps.NNlib.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
[[deps.NVTX]]
deps = ["Colors", "JuliaNVTXCallbacks_jll", "Libdl", "NVTX_jll"]
git-tree-sha1 = "53046f0483375e3ed78e49190f1154fa0a4083a1"
uuid = "5da4648a-3479-48b8-97b9-01cb529c0a1f"
version = "0.3.4"
[[deps.NVTX_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ce3269ed42816bf18d500c9f63418d4b0d9f5a3b"
uuid = "e98f9f5b-d649-5603-91fd-7774390e6439"
version = "3.1.0+2"
[[deps.OneHotArrays]]
deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"]
git-tree-sha1 = "963a3f28a2e65bb87a68033ea4a616002406037d"
uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
version = "0.2.5"
[[deps.Optimisers]]
deps = ["ChainRulesCore", "Functors", "LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "c9ff5c686240c31eb8570b662dd1f66f4b183116"
uuid = "3bd65402-5787-11e9-1adc-39752487f4e2"
version = "0.3.4"
[[deps.Random123]]
deps = ["Random", "RandomNumbers"]
git-tree-sha1 = "4743b43e5a9c4a2ede372de7061eed81795b12e7"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.7.0"
[[deps.RandomNumbers]]
deps = ["Random"]
git-tree-sha1 = "c6ec94d2aaba1ab2ff983052cf6a606ca5985902"
uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143"
version = "1.6.0"
[[deps.StructArrays]]
deps = ["ConstructionBase", "DataAPI", "Tables"]
git-tree-sha1 = "f4dc295e983502292c4c3f951dbb4e985e35b3be"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.18"
weakdeps = ["Adapt", "GPUArraysCore", "SparseArrays", "StaticArrays"]
[deps.StructArrays.extensions]
StructArraysAdaptExt = "Adapt"
StructArraysGPUArraysCoreExt = "GPUArraysCore"
StructArraysSparseArraysExt = "SparseArrays"
StructArraysStaticArraysExt = "StaticArrays"
[[deps.ThreadsX]]
deps = ["Accessors", "ArgCheck", "BangBang", "ConstructionBase", "InitialValues", "MicroCollections", "Referenceables", "SplittablesBase", "Transducers"]
git-tree-sha1 = "70bd8244f4834d46c3d68bd09e7792d8f571ef04"
uuid = "ac1d9e8a-700a-412c-b207-f0111f4b6c0d"
version = "0.1.12"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "3a6f063d690135f5c1ba351412c82bae4d1402bf"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.25"
[[deps.Transducers]]
deps = ["Accessors", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "ConstructionBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "SplittablesBase", "Tables"]
git-tree-sha1 = "7deeab4ff96b85c5f72c824cae53a1398da3d1cb"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.84"
[deps.Transducers.extensions]
TransducersAdaptExt = "Adapt"
TransducersBlockArraysExt = "BlockArrays"
TransducersDataFramesExt = "DataFrames"
TransducersLazyArraysExt = "LazyArrays"
TransducersOnlineStatsBaseExt = "OnlineStatsBase"
TransducersReferenceablesExt = "Referenceables"
[deps.Transducers.weakdeps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
[[deps.UnsafeAtomics]]
git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278"
uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f"
version = "0.2.1"
[deps.Unitful.weakdeps]
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.UnsafeAtomicsLLVM]]
deps = ["LLVM", "UnsafeAtomics"]
git-tree-sha1 = "2d17fabcd17e67d7625ce9c531fb9f40b7c42ce4"
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
version = "0.2.1"
[[deps.Zygote]]
deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"]
git-tree-sha1 = "f816633be6dc5c0ed9ffedda157ecfda0b3b6a69"
uuid = "e88e6eb3-aa80-5325-afca-941959d7151f"
version = "0.6.72"
[deps.Zygote.extensions]
ZygoteColorsExt = "Colors"
ZygoteDistancesExt = "Distances"
ZygoteTrackerExt = "Tracker"
[deps.Zygote.weakdeps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
[[deps.ZygoteRules]]
deps = ["ChainRulesCore", "MacroTools"]
git-tree-sha1 = "27798139afc0a2afa7b1824c206d5e87ea587a00"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.5"
[[deps.cuDNN]]
deps = ["CEnum", "CUDA", "CUDA_Runtime_Discovery", "CUDNN_jll"]
git-tree-sha1 = "4b3ac62501ca73263eaa0d034c772f13c647fba6"
uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
version = "1.4.0"
[[deps.demumble_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
git-tree-sha1 = "6498e3581023f8e530f34760d18f75a69e3a4ea8"
uuid = "1e29f10c-031c-5a83-9565-69cddfc27673"
version = "1.3.0+0"