o
    SQ8jϳ                     @   s  d dl Z d dl mZmZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Zd dlZd dlZd dlZd dlZd dlmZ d dlZd dlmZ d dlZd dlmZmZmZ d dlmZ d dlmZ G dd	 d	ejZd
d Zedkr
e  Z!e!j"dde#dd e!j"dddddd e!j"dddddd e!j"dddddd e!j"dddddd e!$ Z%e&e'e%j(d) ej*Z+ej,-d ej,.e+d  d dl/m/Z/ ej,.e+d  e+d < ej,0e+d  se1e+d   ej,0ej,2e+d  e+d! se1ej,2e+d  e+d!  ej,2e+d  e+d! d"Z3ej,2e+d  e+d! d#Z4ej,2e+d  e+d! d$Z5ej,2e+d  e+d! d%Z6ej,2e+d  e+d! Z7d&d' e+d( D Z8g Z9e:e+d) e:e+d* krfd+ge:e+d*  e+d)< e;e+d* e+d) D ]\Z<Z=e9>d,d' e?e<D e=  qoe%j@du reAd- ej,0e3se1e3 e:eBe3ZCeCd.e+d/  kre/e+d0 e+d/ eC e+d1 d2gd2gg d3e3dd4d' eDe+d/ D d5	 e jEF  neGd6e+d/  d7 eAd8 ej,0e4se1e4 e:eBe4ZCeCd.e+d9  kre/e+d0 e+d9 eC e+d1 d:gd:gg d3e4dd; e jEF  neGd<e+d9  d7 eAd= ej,0e5s9e1e5 e:eBe5ZCeCd.e+d/  kre+d> ZHe+d0 D ]ZIeH>eeIe+d/ e:e+d0  d:d?d@ qQe/eHe+d/ eC e+d1 dA d2gd2gg d3e5ddBd' eDe+d/ D d5	 e jEF  neGdCe+d/  d7 eAdD ej,0e6se1e6 e:eBe6ZCeCd.e+d9  kre+d> ZHe+d0 D ]ZIeH>eeIe+d9 e:e+d0  d:d?d@ qe/eHe+d9 eC e+d1 dA d:gd:gg d3e6dd; e jEF  neGdEe+d9  d7 dFZJdGd' ee4KdHD ZLg ZMeDeJD ]ZNejOjP)eLejQRd e:eL \ZSZTeMUe:eT qeVeWeXeMdI dI dJ e+dK< e+dK dLk rRdLe+dK< neYe+dK dL dMkradLe+dK< e%jdu rej,0ej,2e7dNrye%jZdu rdOd' ee3KdHD e+dP  Z[ee[e+dK e+dQ e9e8dRZ\dSd' ee4KdHD e+dP  Z]ee]e+dK e+dQ e9e8dRZ^dTd' ee5KdHD e+dP  Z_ee_e+dK e+dQ e9e8dRZ`dUd' ee6KdHD e+dP  Zaeeae+dK e+dQ e9e8dRZbeAdV ec Zdeddu rd+ZdneddW Zdee\e:eBe3e+dK ej,2e7dNe jEe rdXndYe jEe s$ednd+dZ ee`e:eBe5e+dK ej,2e7d[e jEe rAdXndYe jEe sJednd+dZ ee^e:eBe4e+dK ej,2e7d\e jEe rgdXndYe jEe spednd+dZ eebe:eBe6e+dK ej,2e7d]e jEe rdXndYe jEe sednd+dZ neGd^ e%jfdu rejgjdYd_Zhehie+dK d` Zjed+eje+da e+db dcejd   d` ddZkddfdgZldhdi e+dj m D Zni Zodkgepe+dj m  dlg D ]Zqeqdkkrdmdn eoeq< qdodn eoeq< qej,2e7dNe+dj dk< ej,2e7d[e+dj dl< ee+dj e+dp eneodqZrG drds dse jgjsjtZuec Zdeddu r9d+ZdneddW Zde jgjsjveuerdeddedtZwe&e+du Zxeydvd' eDd exjzd  ejd   d+D Zxe{exjzd  |ej}Z~e jgjsjve jgjse exe e~e:e~dwZxe&ej,2e7d\Ze&ej,2e7d]Zeeejzd  e{ejzd  f|ej}Ze jgjsjve jgjse eeefe ee:edwZekjeweexe+dx e+dy e+dz d{Zekjee+d! e+d  d| eej,2e+d  e+d! d} ej,2e+d  e+d! d~  dS dS dS )    N)optimnn)tqdm)Path)generate_adversarial_textsaugment_clipsmmap_batch_generator)compute_features_from_generator)AudioFeaturesc                       s   e Zd Z		d+ fdd	Zdd	 Zd,ddZ					d-ddZdd Zdd Zd.ddZ	d/ddZ
		d0dd Zd.d!d"Zd.d#d$Zd%d& Zddddgd'gd(dfd)d*Z  ZS )1Model      `   dnn   Nc                    sr  t    || _|| _|| _ttj rdnd| _g | _	g | _
d| _d| _d| _d| _|dkrOG dd dtj G  fdd	d	tj}|||||d
| _n|dkrbG dd	 d	tj}|||| _|dkrzdd | _tjdd| _tjdd| _nddd}ddd}	ddd}
|| _|
| _|	| _d| _d| _tt| _|dkrtjjj ntjj!| _"t#j$| j% dd| _&d S )Nzcuda:0cpu  r   r   c                       s$   e Zd Z fddZdd Z  ZS )z Model.__init__.<locals>.FCNBlockc                    s2   t    t||| _t | _t|| _d S N)	super__init__r   Linear	fcn_layerReLUrelu	LayerNorm
layer_norm)self	layer_dim	__class__ Y/home/nk/hobo-godmode/plappi-mvp/.venv/lib/python3.10/site-packages/openwakeword/train.pyr   9   s   

z)Model.__init__.<locals>.FCNBlock.__init__c                 S   s   |  | | |S r   )r   r   r   r   xr!   r!   r"   forward?   s   z(Model.__init__.<locals>.FCNBlock.forward__name__
__module____qualname__r   r%   __classcell__r!   r!   r   r"   FCNBlock8   s    r+   c                       s(   e Zd Zd fdd	Zdd Z  ZS )Model.__init__.<locals>.Netr   c                    s   t    t | _t|d |d   | _t | _t	 | _
t fddt|D | _t || _|dkrDt | _d S t | _d S )Nr   r   c                    s   g | ]} qS r!   r!   .0i)r+   r   r!   r"   
<listcomp>I       z8Model.__init__.<locals>.Net.__init__.<locals>.<listcomp>)r   r   r   Flattenflattenr   layer1r   relu1r   
layernorm1
ModuleListrangeblocks
last_layerSigmoidlast_act)r   input_shaper   n_blocks	n_classes)r+   r    )r   r"   r   C   s   


 $$Model.__init__.<locals>.Net.__init__c              	   S   sD   |  | | | |}| jD ]}||}q| | |}|S r   )r5   r6   r4   r3   r9   r<   r:   )r   r$   blockr!   r!   r"   r%   M   s
   

#Model.__init__.<locals>.Net.forward)r   r   r&   r!   r+   r   r"   NetB   s    
rD   )r>   r?   rnnc                       s&   e Zd Zd fdd	Zdd Z  ZS )r,   r   c                    sX   t    tj|d dddddd| _td|| _|dkr%t | _	d S t | _	d S )	N@      T        )
num_layersbidirectionalbatch_firstdropoutr   r   )
r   r   r   LSTMr4   r   layer2r;   r   layer3)r   r=   r?   r   r!   r"   r   V   s   
$r@   c                 S   s*   |  |\}}| | |d d df S )NrF   )r4   rP   rO   )r   r$   outhr!   r!   r"   r%   ]   s   rB   r   r&   r!   r!   r   r"   rD   U   s    r   c                 S   s   ||  dk  S )Ng      )sum)predyr!   r!   r"   <lambda>d       z Model.__init__.<locals>.<lambda>binary)task      ?c                 S   sN   t jjj| dd}|dk}|| jddd|| jddd |k@ k }|S Nr   dimr   axistorchr   
functionalsoftmaxargmaxmaxrT   )prV   	thresholdprobsneg_ndcsfpr!   r!   r"   multiclass_fph   s   0z%Model.__init__.<locals>.multiclass_fpc                 S   sV   t jjj| dd}|dk}|| jddd|| jddd |k@ k |  }|S r\   ra   )rg   rV   negative_class_labelrh   ri   pos_ndcsrcllr!   r!   r"   positive_class_recalln   s   
z-Model.__init__.<locals>.positive_class_recallc                 S   sJ   t jjj| dd}|jdd|k}|| jdd|| k |  }|S )Nr   r]   r_   )rb   r   rc   rd   re   rT   )rg   rV   rm   ri   	pos_predsaccr!   r!   r"   positive_class_accuracyu   s   $z/Model.__init__.<locals>.positive_class_accuracy-C6?)lr)r[   )r   r[   r   )'r   r   r?   r=   seconds_per_examplerb   devicecudais_availablebest_modelsbest_model_scoresbest_val_fpbest_val_accuracybest_val_recallbest_train_recallr   Modulemodelrk   torchmetricsRecallrecallAccuracyaccuracyrr   n_fpval_fpcollectionsdefaultdictlisthistoryrc   binary_cross_entropycross_entropylossr   Adam
parameters	optimizer)r   r?   r=   
model_typer   r>   rw   rD   rl   rp   rs   r   rC   r"   r      sB   





zModel.__init__c                 C   s    | j dkrt| j| dS dS )z>
        Saves the weights of a trained Pytorch model
        r   N)r?   rb   saver   )r   output_pathr!   r!   r"   
save_model   s   
zModel.save_model c                    s   |  | j dkrtjj| jdt| jd ||gd d S | j dkrBG  fdddtj	}tjj| t| jd ||gd d S d S )Nr   r   r   )output_namesc                       s&   e Zd Z fddZdd Z  ZS )zModel.export_to_onnx.<locals>.Mc                    s   t    jd| _d S )Nr   )r   r   r   tor   )r    objr!   r"   r      s   
z(Model.export_to_onnx.<locals>.M.__init__c                 S   s   t jjj| |ddS )Nr   r]   )rb   r   rc   rd   r   r#   r!   r!   r"   r%         z'Model.export_to_onnx.<locals>.M.forwardr&   r!   r   r   r"   M   s    r   )
r?   rb   onnxexportr   r   randr=   r   r   )r   r   class_mappingr   r!   r   r"   export_to_onnx   s   
 


zModel.export_to_onnxr   rI   MbP?c           	      C   st   d| dt t j|| |  t|| |    }|||  }|dkr/t ||| k||}t ||k ||}|S )Nr[   r   r   )npcospifloatwhere)	r   global_stepwarmup_stepsholdtotal_stepsstart_lr	target_lrlearning_rate	warmup_lrr!   r!   r"   lr_warmup_cosine_decay   s   	
zModel.lr_warmup_cosine_decayc                 C   s
   |  |S r   r   r#   r!   r!   r"   r%         
zModel.forwardc                 C   s   t j| jd| j ddS )NrS   r   )
input_sizerx   )	torchinfosummaryr   r=   r   r!   r!   r"   r      r   zModel.summaryc                 C   s   |du r| j }t|d }| }|D ]
}||  d9  < q|D ]}| }| D ]\}}||  |7  < q+q!|D ]}||  t|  < q;|| |S )zHAverages the weights of the provided models together to make a new modelNr   )r{   copydeepcopy
state_dictitemslenload_state_dict)r   modelsaveraged_modelaveraged_model_dictkeyr   
model_dictvaluer!   r!   r"   average_models   s   
zModel.average_models皙&@r[   皙?c                    s~  dgt j }|D ]Q}|d j|d j}}ttjt jddD ]0\}	}
t   |
|}||	 ||d 	 
   ||	< W d   n1 sUw   Y  q*q
fdd|D } fd	dt|D }fd
d|D }t||krtd| d dS j|t|  }j|t|  d }td| dt | dt| d||t|    |S )a?  
        Select the top model based on the false positive rate on the validation data

        Args:
            false_positive_validate_data (torch.DataLoader): A dataloader with validation data
            n (int): The number of models to select

        Returns:
            list: A list of the top n models
        r   r   z,Find best checkpoints by false positive ratetotaldesc.NNc                    s   g | ]}|  qS r!   r!   )r.   rk   )val_set_hrsr!   r"   r0      r1   z,Model._select_best_model.<locals>.<listcomp>c                    s   g | ]
\}}| kr|qS r!   r!   )r.   ndxrk   )max_fp_per_hourr!   r"   r0      s    c                    s   g | ]	} j | d  qS )
val_recall)r|   )r.   r   r   r!   r"   r0          zNo models with recall >= z found!training_step_ndxzBest model from training step z out of zmodels has recall of z and false positive rate of )r   r{   r   rx   r   	enumeraterb   no_gradrk   detachr   numpyrf   loggingwarningr   re   r|   info)r   false_positive_validate_datar   r   
min_recallfalse_positive_ratesbatchx_valy_valmdl_ndxr   val_pscandidate_model_ndxcandidate_model_recall
best_modelbest_model_training_stepr!   )r   r   r   r"   _select_best_model   s4   "
*zModel._select_best_modelP  r   c                 C   sN  d}t d d}td|t| }	t|t|d  |dtj}
| j|||||	|
|d |d ||d	
 t d
 |d }|d }| j	|krS|d }t d td|t| }	td|dtj
}
| j|||||	|
|d |d ||d	
 t d |d }| j	|kr|d }t d td|t| }	td|dtj
}
| j|||||	|
|d |d ||d	
 t d t| jd d}t| jd d}t| jd d}g }t| j| jD ]\}}|d |kr|d |kr|d |kr|| qt|dkr| j|d}n| j}t t |D ]}|d | j|d | j}}||}q| ||d    }| ||d tj   }d}|D ]"}|d | j|d | j}}||}|| ||d 7 }qY||    }W d   n	1 sw   Y  t d| d| d| d |S )zA sequence of training steps that produce relatively strong models
        automatically, based on validation data and performance targets provided.
        After training merges the best checkpoints and returns a single model.
        r   z##################################################
Starting training sequence 1...
##################################################rt   r   g      ?         )
XX_valfalse_positive_val_data	max_stepsnegative_weight_schedule	val_stepsr   
hold_stepsru   r   z##################################################
Starting training sequence 2...
##################################################
   rH   zCIncreasing weight on negative examples to reduce false positives...z##################################################
Starting training sequence 3...
##################################################zBMerging checkpoints above the 90th percentile into single model...val_accuracyZ   r   val_fp_per_hrr   )r   r   Nz(
################
Final Model Accuracy: z
Final Model Recall: z'
Final Model False Positives per Hour: z
################
)r   r   r   linspaceinttolistastypeint64train_modelr}   int16
percentiler   zipr{   r|   appendr   r   r   rb   r   r   rx   r   r   r   r   r   rk   )r   X_trainr   r   stepsmax_negative_weighttarget_fp_per_hourr   ru   weightsr   accuracy_percentilerecall_percentilefp_percentiler   r   scorecombined_modelr   r$   rV   r   combined_model_recallcombined_model_accuracycombined_model_fpr   r   combined_model_fp_per_hrr!   r!   r"   
auto_train  s   
"














"$"
zModel.auto_trainc              	   C   s   t |dk r
|d }|| j}g }t|ddD ]H}|d }g }td|jd d dD ]}||dd||d ddf  q+t|}|du rO| 	|}n||}||
   d  qt|S )	a  
        Predict on Tensors of openWakeWord features corresponding to single audio clips

        Args:
            features (torch.Tensor): A Tensor of openWakeWord features with shape (batch, features)
            model (torch.nn.Module): A Pytorch model to use for prediction (default None, which will use self.model)

        Returns:
            torch.Tensor: An array of predictions of shape (batch, prediction), where 0 is negative and 1 is positive
        r   r   zPredicting on clips)r   r   r   r   N)r   r   rx   r   r8   shaper   rb   vstackr   r   r   r   r   )r   featuresr   predictionsr$   r   r/   predsr!   r!   r"   predict_on_featuresp  s   &

zModel.predict_on_featuresc                 C   s2   t ddd}|j|dd}| jt||d}|S )a  
        Predict on Tensors of 16-bit 16 khz audio data

        Args:
            clips (np.ndarray): A Numpy array of audio clips with shape (batch, samples)
            model (torch.nn.Module): A Pytorch model to use for prediction (default None, which will use self.model)

        Returns:
            np.ndarray: An array of predictions of shape (batch, prediction), where 0 is negative and 1 is positive
        r      )rx   ncpur   
batch_sizer   )r
   embed_clipsr  rb   
from_numpy)r   clipsr   Fr  r  r!   r!   r"   predict_on_clips  s   zModel.predict_on_clipsc                 C   st   | j dkr	tdtdtj||d  d t|}t	j
j|dt	| jd tj||d dd	 d
S )zDSaves the trained openwakeword model to both onnx and tflite formatsr   zExporting models to both onnx and tflite with more than one class is currently not supported! Use the `export_to_onnx` function instead.z####
Saving ONNX mode as '.onnx'r   r      )opset_versionN)r?   
ValueErrorr   r   ospathjoinr   r   rb   r   r   r   r   r=   )r   r   
model_name
output_dirmodel_to_saver!   r!   r"   export_model  s   
 
zModel.export_model   rt   c           *      C   s  |  | j | j | j d}d}tg  | j}tg  | j}tt|d|ddD ]7\}}|d  | j|d  | j}}|d  tj}| jj	D ]}| j
|||||
d|d< qO| j  | |}||dk| dk@  }||dk| d	k @  }t||dk| dk@  ||dk| d	k @  f}|d  tj}t||f}t|dkrt|jd |d  }|dk}d||< |d }n| jdkrt|jd ||  }|dk}d||< |d }|jd dkr| || jdkr|n|| | j}|| }||jd 7 }|jd d
kr|}|}|d
k r/|d7 }t||f}t||f}nT|  | j  d}d}| jd |    | || jdkrU|n|}|  j|7  _| jd | ||    tg  | j}tg  | j}||	v r|dkr|d urd}t|D ]:\}}t ( |d  | j|d  | j}} | |}!|| |!| d 7 }W d    n	1 sw   Y  q||    }"| jd |" ||	v rh|dkrh|d urhd}#d}$t|D ]_\}}t M |d  | j}g }%td|jd d dD ]}&|%|d d |&|&d d d f  qt|%}%| |%}'t |'dkrF|#d7 }#n|$d7 }$W d    n	1 sUw   Y  q| jd |#|#|$   ||	v r|dkr|d urt|D ]R\}}t @ |d  | j|d  | j}} | |}!| |!| d    }(| !|!| d  tj"})| |!| d }W d    n	1 sw   Y  q{| jd |)    | jd |( | jd |    ||	v r[|dkr[| jd d t#$| jd dkr[| jd d t#$| jd dkr[| j%t&'| j | j(|| jd d | jd d | jd d | j)ddgd d | jd d | _*| jd d | _+||d kre d S q-d S )Nr   r   Trainingr   r   )r   r   r   r   ru   r   g+?r   r   r   r   r   r[   positive_test_clips_recallr   r   val_n_fprF   2   r   )r   r,  r   r   r   ),r   rx   r   rb   Tensorr   r   float32r   param_groupsr   	zero_gradsqueezecatr   onesr  r?   r   backwardstepr   r   r   r   r   rk   r   r   r   r8   r  anyr   r   r   r   r{   r   r   r|   getr   r~   )*r   r   r   r   r   r   r   positive_test_clipsr   r   ru   r   accumulation_stepsaccumulated_samplesaccumulated_predictionsaccumulated_labelsstep_ndxdatar$   rV   y_gr  neg_high_losspos_high_losswrn   r   rk   r   val_step_ndxr   r   val_predictionsr   tpfnr   r/   r  r   val_accr!   r!   r"   r     s   "


6

$

$
"

(



"
""zModel.train_model)r   r   r   r   r   N)r   )r   r   r   rI   r   r   )r   r[   r   )r   r   r   )r'   r(   r)   r   r   r   r   r%   r   r   r   r  r  r  r(  r   r*   r!   r!   r   r"   r      s6    o



$

k
r   c              	   C   s   ddl }ddlm} ddl}|| }||dd}t N}|tj	
|d |jjtj	
|d}| }	td| d t|d	}
|
|	 W d   n1 sVw   Y  W d   dS W d   dS 1 snw   Y  dS )
zRConverts an ONNX version of an openwakeword model to the Tensorflow tflite format.r   N)prepareCPUrx   tf_modelz####
Saving tflite mode to 'r  wb)r   onnx_tf.backendrJ  
tensorflowloadtempfileTemporaryDirectoryexport_graphr"  r#  r$  liteTFLiteConverterfrom_saved_modelconvertr   r   openwrite)onnx_model_pathr   r   rJ  tf
onnx_modeltf_reptmp_dir	convertertflite_modelfr!   r!   r"   convert_onnx_to_tflite>  s(   


	
		rc  __main__z--training_configz/The path to the training config file (required)T)helptyperequiredz--generate_clipsz-Execute the synthetic data generation process
store_trueFalseF)re  actiondefaultrg  z--augment_clipsz/Execute the synthetic data augmentation processz--overwritezNOverwrite existing openwakeword features when the --augment_clips flag is usedz--train_modelz"Execute the model training processrpiper_sample_generator_path)generate_samplesr&  r%  positive_trainpositive_testnegative_trainnegative_testc                 C   s"   g | ]}t |D ]}|jq	qS r!   )r"  scandirr#  )r.   jr/   r!   r!   r"   r0     s   " r0   	rir_paths!background_paths_duplication_ratebackground_pathsr   c                 C   s   g | ]}|j qS r!   )r#  r-   r!   r!   r"   r0         z##################################################
Generating positive clips for training
##################################################gffffff?	n_samplestarget_phrasetts_batch_sizeg\(\?)g      ?      ?g      ?c                 C      g | ]	}t  jd  qS z.wavuuiduuid4hexr-   r!   r!   r"   r0     r   )	textmax_samplesr  noise_scalesnoise_scale_wslength_scalesr&  auto_reduce_batch_size
file_namesz8Skipping generation of positive clips for training, as ~z already existz##################################################
Generating positive clips for testing
##################################################n_samples_valr|  )r  r  r  r  r  r  r&  r  z3Skipping generation of positive clips testing, as ~z##################################################
Generating negative clips for training
##################################################custom_negative_phrasesr   )
input_textNinclude_partial_phraseinclude_input_words   c                 C   r}  r~  r  r-   r!   r!   r"   r0     r   z8Skipping generation of negative clips for training, as ~z##################################################
Generating negative clips for testing
##################################################z7Skipping generation of negative clips for testing, as ~r-  c                 C      g | ]}t |qS r!   strr-   r!   r!   r"   r0     r1   z*.wavr   i.  total_lengthi }  i  zpositive_features_train.npyc                 C   r  r!   r  r-   r!   r!   r"   r0     r1   augmentation_roundsaugmentation_batch_size)r  r  background_clip_paths	RIR_pathsc                 C   r  r!   r  r-   r!   r!   r"   r0     r1   c                 C   r  r!   r  r-   r!   r!   r"   r0      r1   c                 C   r  r!   r  r-   r!   r!   r"   r0     r1   z##################################################
Computing openwakeword features for generated samples
##################################################rH   gpur   )n_totalclip_durationoutput_filerx   r  znegative_features_train.npyzpositive_features_test.npyznegative_features_test.npyzVOpenwakeword features already exist, skipping data augmentation and feature generationrL  i>  r   
layer_sizei   )r?   r=   r   r   rw   r   c                    sZ    j d ks j d k r+tt fddtdj d    D }|S S )zbSimple transformation function to ensure negative data is the appropriate shape for the model sizer   c                    s$   g | ]}||  d d f qS r   r!   r-   nr$   r!   r"   r0   :  s   $ zf.<locals>.<listcomp>r   )r  r   r  arrayr8   )r$   r  	new_batchr!   r  r"   rb  6  s
   
,rb  c                 C   s   i | ]}|t qS r!   )rb  )r.   r   r!   r!   r"   
<dictcomp>@  rx  r  feature_data_filespositiveadversarial_negativec                 C      dd | D S )Nc                 S      g | ]}d qS rS   r!   r-   r!   r!   r"   r0   D  rX   <lambda>.<locals>.<listcomp>r!   r$   r!   r!   r"   rW   D      rW   c                 C   r  )Nc                 S   r  rv   r!   r-   r!   r!   r"   r0   F  rX   r  r!   r  r!   r!   r"   rW   F  r  batch_n_per_class)n_per_classdata_transform_funcslabel_transform_funcsc                   @   s   e Zd Zdd Zdd ZdS )IterDatasetc                 C   s
   || _ d S r   	generator)r   r  r!   r!   r"   r   U  r   zIterDataset.__init__c                 C   s   | j S r   r  r   r!   r!   r"   __iter__X  s   zIterDataset.__iter__N)r'   r(   r)   r   r  r!   r!   r!   r"   r  T  s    r  )r  num_workersprefetch_factor#false_positive_validation_data_pathc                 C   s    g | ]}t ||td    qS rv   )X_val_fpr=   r-   r!   r!   r"   r0   d  s     r  r   r  target_false_positives_per_hour)r   r   r   r   r  r  )r   r%  r&  r  z.tflite)r   )rb   r   r   r   r   r   r"  sysrR  r  r   r   scipyr   argparser   r   yamlpathlibr   openwakewordopenwakeword.datar   r   r   openwakeword.utilsr	   r
   r   r   rc  r'   ArgumentParserparseradd_argumentr  
parse_argsargsrQ  rY  training_configreadLoaderconfigr#  insertabspathrn  existsmkdirr$  positive_train_output_dirpositive_test_output_dirnegative_train_output_dirnegative_test_output_dirfeature_save_dirru  rw  r   r   background_pathduplication_rateextendrs  generate_clipsr   listdirn_current_samplesr8   ry   empty_cacher   adversarial_textsrz  r  globpositive_clipsduration_in_samplesr/   iowavfilerandomrandintsrdatr   r   roundmedianabs	overwritepositive_clips_trainpositive_clips_train_generatorpositive_clips_testpositive_clips_test_generatornegative_clips_trainnegative_clips_train_generatornegative_clips_testnegative_clips_test_generator	cpu_countn_cpusrz   r   utilsr  get_embedding_shaper=   owwrb  keysdata_transformslabel_transformsr   r   batch_generatorr?  IterableDatasetr  
DataLoaderr   r  r  r  zerosr   r/  X_val_fp_labelsTensorDatasetr  	X_val_pos	X_val_neghstackr4  labelsr  r   r  r   r(  r!   r!   r!   r"   <module>   s2       )
 "









$"
$ 
 
 
 





 

*.	
   [