2017-07-20 1 views
2

Je suis en train de créer un fichier .csv à partir d'une table lua. J'ai lu une partie de la documentation en ligne et sur ce forum ... mais je n'arrive pas à l'obtenir. Je pense que c'est à cause du format de la table lua - regardez par vous-même.Création d'un fichier .CSV à partir d'une table Lua

Ce script provient d'un excellent logiciel open-source appelé NeuralTalk2. Le point principal du logiciel est de légender des images. Vous pouvez en savoir plus sur cette page.

Quoi qu'il en soit, permettez-moi de vous présenter le premier morceau de code: une fonction qui prend la table lua et l'écrit dans un fichier .json. Voici comment il ressemble:

function utils.write_json(path, j) 
    -- API reference http://www.kyne.com.au/~mark/software/lua-cjson-manual.html#encode 
    cjson.encode_sparse_array(true, 2, 10) 
    local text = cjson.encode(j) 
    local file = io.open(path, 'w') 
    file:write(text) 
    file:close() 
end 

Une fois que le code est compilé, le fichier .json ressemble à ceci:

[{"caption":"a view of a UNK UNK in a cloudy sky","image_id":"0001"},{"caption":"a view of a UNK UNK in a cloudy sky","image_id":"0002"}] 

Il va beaucoup plus longtemps, mais en général, il y a une « légende » suivante par un texte, et un "image_id" suivi de l'id de l'image.

Lorsque j'imprime la table sur le terminal, il ressemble à ceci:

{ 
    1681 : 
    { 
     caption : "a person holding a cell phone in their hand" 
     image_id : "1681" 
    } 
    1682 : 
    { 
     caption : "a person is taking a picture of a mirror" 
     image_id : "1682" 
    } 
} 

Il a des choses avant et après ... Je suis juste vous montrer le format général de la table.

Vous vous demandez peut-être comment la table est définie ... Je ne suis pas sûr qu'il existe une définition très claire à l'intérieur du script. Je vais le partager juste pour vous de voir, le fichier où il est défini dépend de tant d'autres fichiers, donc c'est en désordre. J'espere de la sortie du terminal, vous pouvez comprendre en general la structure de la table, et a partir de ce savoir comment la table est structuree. Je veux le sortir dans un fichier .csv qui ressemblera à ceci

image_id  captions 
1   xxxx 
2   xxxx 
3   xxxx 

Comment puis-je faire ceci ..? Pas sûr, compte tenu du format de la table lua ...

Voici le script où il est défini. Plus précisément, il est défini à la fin, mais encore une fois, pas sûr que ce soit trop d'aide.

require 'torch' 
require 'nn' 
require 'nngraph' 
-- exotics 
require 'loadcaffe' 
-- local imports 
local utils = require 'misc.utils' 
require 'misc.DataLoader' 
require 'misc.DataLoaderRaw' 
require 'misc.LanguageModel' 
local net_utils = require 'misc.net_utils' 
local csv_utils = require 'misc.csv_utils' 

------------------------------------------------------------------------------- 
-- Input arguments and options 
------------------------------------------------------------------------------- 
cmd = torch.CmdLine() 
cmd:text() 
cmd:text('Train an Image Captioning model') 
cmd:text() 
cmd:text('Options') 

-- Input paths 
cmd:option('-model','','path to model to evaluate') 
-- Basic options 
cmd:option('-batch_size', 1, 'if > 0 then overrule, otherwise load from checkpoint.') 
cmd:option('-num_images', 100, 'how many images to use when periodically evaluating the loss? (-1 = all)') 
cmd:option('-language_eval', 0, 'Evaluate language as well (1 = yes, 0 = no)? BLEU/CIDEr/METEOR/ROUGE_L? requires coco-caption code from Github.') 
cmd:option('-dump_images', 1, 'Dump images into vis/imgs folder for vis? (1=yes,0=no)') 
cmd:option('-dump_json', 1, 'Dump json with predictions into vis folder? (1=yes,0=no)') 
cmd:option('-dump_path', 0, 'Write image paths along with predictions into vis json? (1=yes,0=no)') 
-- Sampling options 
cmd:option('-sample_max', 1, '1 = sample argmax words. 0 = sample from distributions.') 
cmd:option('-beam_size', 2, 'used when sample_max = 1, indicates number of beams in beam search. Usually 2 or 3 works well. More is not better. Set this to 1 for faster runtime but a bit worse performance.') 
cmd:option('-temperature', 1.0, 'temperature when sampling from distributions (i.e. when sample_max = 0). Lower = "safer" predictions.') 
-- For evaluation on a folder of images: 
cmd:option('-image_folder', '', 'If this is nonempty then will predict on the images in this folder path') 
cmd:option('-image_root', '', 'In case the image paths have to be preprended with a root path to an image folder') 
-- For evaluation on MSCOCO images from some split: 
cmd:option('-input_h5','','path to the h5file containing the preprocessed dataset. empty = fetch from model checkpoint.') 
cmd:option('-input_json','','path to the json file containing additional info and vocab. empty = fetch from model checkpoint.') 
cmd:option('-split', 'test', 'if running on MSCOCO images, which split to use: val|test|train') 
cmd:option('-coco_json', '', 'if nonempty then use this file in DataLoaderRaw (see docs there). Used only in MSCOCO test evaluation, where we have a specific json file of only test set images.') 
-- misc 
cmd:option('-backend', 'cudnn', 'nn|cudnn') 
cmd:option('-id', 'evalscript', 'an id identifying this run/job. used only if language_eval = 1 for appending to intermediate files') 
cmd:option('-seed', 123, 'random number generator seed to use') 
cmd:option('-gpuid', 0, 'which gpu to use. -1 = use CPU') 
cmd:text() 

------------------------------------------------------------------------------- 
-- Basic Torch initializations 
------------------------------------------------------------------------------- 
local opt = cmd:parse(arg) 
torch.manualSeed(opt.seed) 
torch.setdefaulttensortype('torch.FloatTensor') -- for CPU 

if opt.gpuid >= 0 then 
    require 'cutorch' 
    require 'cunn' 
    if opt.backend == 'cudnn' then require 'cudnn' end 
    cutorch.manualSeed(opt.seed) 
    cutorch.setDevice(opt.gpuid + 1) -- note +1 because lua is 1-indexed 
end 

------------------------------------------------------------------------------- 
-- Load the model checkpoint to evaluate 
------------------------------------------------------------------------------- 
assert(string.len(opt.model) > 0, 'must provide a model') 
local checkpoint = torch.load(opt.model) 
-- override and collect parameters 
if string.len(opt.input_h5) == 0 then opt.input_h5 = checkpoint.opt.input_h5 end 
if string.len(opt.input_json) == 0 then opt.input_json = checkpoint.opt.input_json end 
if opt.batch_size == 0 then opt.batch_size = checkpoint.opt.batch_size end 
local fetch = {'rnn_size', 'input_encoding_size', 'drop_prob_lm', 'cnn_proto', 'cnn_model', 'seq_per_img'} 
for k,v in pairs(fetch) do 
    opt[v] = checkpoint.opt[v] -- copy over options from model 
end 
local vocab = checkpoint.vocab -- ix -> word mapping 

------------------------------------------------------------------------------- 
-- Create the Data Loader instance 
------------------------------------------------------------------------------- 
local loader 
if string.len(opt.image_folder) == 0 then 
    loader = DataLoader{h5_file = opt.input_h5, json_file = opt.input_json} 
else 
    loader = DataLoaderRaw{folder_path = opt.image_folder, coco_json = opt.coco_json} 
end 

------------------------------------------------------------------------------- 
-- Load the networks from model checkpoint 
------------------------------------------------------------------------------- 
local protos = checkpoint.protos 
protos.expander = nn.FeatExpander(opt.seq_per_img) 
protos.crit = nn.LanguageModelCriterion() 
protos.lm:createClones() -- reconstruct clones inside the language model 
if opt.gpuid >= 0 then for k,v in pairs(protos) do v:cuda() end end 

------------------------------------------------------------------------------- 
-- Evaluation fun(ction) 
------------------------------------------------------------------------------- 
local function eval_split(split, evalopt) 
    local verbose = utils.getopt(evalopt, 'verbose', true) 
    local num_images = utils.getopt(evalopt, 'num_images', true) 

    protos.cnn:evaluate() 
    protos.lm:evaluate() 
    loader:resetIterator(split) -- rewind iteator back to first datapoint in the split 
    local n = 0 
    local loss_sum = 0 
    local loss_evals = 0 
    local predictions = {} 
    while true do 

    -- fetch a batch of data 
    local data = loader:getBatch{batch_size = opt.batch_size, split = split, seq_per_img = opt.seq_per_img} 
    data.images = net_utils.prepro(data.images, false, opt.gpuid >= 0) -- preprocess in place, and don't augment 
    n = n + data.images:size(1) 

    -- forward the model to get loss 
    local feats = protos.cnn:forward(data.images) 

    -- evaluate loss if we have the labels 
    local loss = 0 
    if data.labels then 
     local expanded_feats = protos.expander:forward(feats) 
     local logprobs = protos.lm:forward{expanded_feats, data.labels} 
     loss = protos.crit:forward(logprobs, data.labels) 
     loss_sum = loss_sum + loss 
     loss_evals = loss_evals + 1 
    end 

    -- forward the model to also get generated samples for each image 
    local sample_opts = { sample_max = opt.sample_max, beam_size = opt.beam_size, temperature = opt.temperature } 
    local seq = protos.lm:sample(feats, sample_opts) 
    local sents = net_utils.decode_sequence(vocab, seq) 
    for k=1,#sents do 
     local entry = {image_id = data.infos[k].id, caption = sents[k]} 
     if opt.dump_path == 1 then 
     entry.file_name = data.infos[k].file_path 
     end 
     table.insert(predictions, entry) 
     if opt.dump_images == 1 then 
     -- dump the raw image to vis/ folder 
     local cmd = 'cp "' .. path.join(opt.image_root, data.infos[k].file_path) .. '" vis/imgs/img' .. #predictions .. '.jpg' -- bit gross 
     print(cmd) 
     os.execute(cmd) -- dont think there is cleaner way in Lua 
     end 
     if verbose then 
     print(string.format('image %s: %s', entry.image_id, entry.caption)) 
     end 
    end 

    -- if we wrapped around the split or used up val imgs budget then bail 
    local ix0 = data.bounds.it_pos_now 
    local ix1 = math.min(data.bounds.it_max, num_images) 
    if verbose then 
     print(string.format('evaluating performance... %d/%d (%f)', ix0-1, ix1, loss)) 
    end 

    if data.bounds.wrapped then break end -- the split ran out of data, lets break out 
    if num_images >= 0 and n >= num_images then break end -- we've used enough images 
    end 

    local lang_stats 
    if opt.language_eval == 1 then 
    lang_stats = net_utils.language_eval(predictions, opt.id) 
    end 

    return loss_sum/loss_evals, predictions, lang_stats 
end 

local loss, split_predictions, lang_stats = eval_split(opt.split, {num_images = opt.num_images}) 
print('loss: ', loss) 
if lang_stats then 
    print(lang_stats) 
end 

if opt.dump_json == 1 then 
    -- dump the json 
    print(split_predictions) 
    utils.write_json('vis/vis.json', split_predictions) 
    csv_utils.write('vis/vis.csv', split_predictions, ";") 
end 

Répondre

1

Si quelqu'un se demande, j'ai compris la solution il y a longtemps.

function nt2_write(path, data, sep) 
    sep = sep or ',' 
    local file = assert(io.open(path, "w")) 
    file:write('Image ID' .. "," .. 'Caption') 
    file:write('\n') 
    for k, v in pairs(data) do 
     file:write(v["image_id"] .. "," .. v["caption"]) 
     file:write('\n') 
    end 
    file:close() 
end 

Bien sûr, vous devrez peut-être modifier les valeurs de chaîne, mais oui. Bonne programmation.

1
{ 
    1681 : 
    { 
     caption : "a person holding a cell phone in their hand" 
     image_id : "1681" 
    } 
    1682 : 
    { 
     caption : "a person is taking a picture of a mirror" 
     image_id : "1682" 
    } 
} 

Chaque {} désigne une table. Le nombre ou le texte devant le signe deux-points est une clé et le contenu derrière le signe deux-points est la valeur stockée dans la table sous cette clé.

Créons une structure de table qui résulterait une sortie comme celle-ci au-dessus:

local myTable = {} 
myTable[1681] = {caption = "a person holding a cell phone in their hand", 
       image_id = "1681"} 
myTable[1682] = {caption = "a person is taking a picture of a mirror", 
       image_id = "1682"} 

Je ne sais pas ce que votre problème est ici. Je pense que la création du fichier csv désiré est plutôt triviale.Tout ce que vous avez besoin est une boucle qui crée une nouvelle ligne pour chaque entrée de table et ajouter la image_id de valeur respective (ou clé) et la légende

une ligne pourrait ressembler à:

local nextLine = myTable[1681].image_id .. "," .. myTable[1681].caption .. "\n" 

Bien sûr, ce n'est pas très belle et vous utiliseriez une boucle pour obtenir tous les éléments de cette table mais je pense que je devrais laisser un peu de travail pour vous aussi;)

+0

Merci l'homme! Désolé, je n'écris pas dans lua À TOUS, j'essaye juste d'obtenir certaines de ces lignes sur un dossier de .csv ainsi je peux les voir mieux. Pensez-vous que vous pouvez me fournir quelque chose qui fonctionne? Ne vous souciez pas trop de l'élégance. Je promets Ill apprendre lua plus tard xD –

+0

@JohnLexus nope. Je ne le ferai pas. Vous ne seriez pas assis dans la rue et vous supplieriez les gens pour 100 dollars, n'est-ce pas? – Piglet

+0

Très bien, c'est logique. Merci pour votre aide de toute façon –