o
    ¢ÄiÏ³  ã                   @   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  ¡sêe 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¡s›e 1e3¡ e:e Be3¡ƒZCeCd.e+d/  krÓe/e+d0 e+d/ eC e+d1 d2gd2gg d3¢e3dd4d'„ eDe+d/ ƒD ƒd5	 e jE F¡  ne Gd6e+d/ › d7¡ e Ad8¡ ej, 0e4¡sïe 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 jE F¡  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 jE F¡  ne GdCe+d/ › d7¡ e AdD¡ ej, 0e6¡s¬e 1e6¡ e:e Be6¡ƒZCeCd.e+d9  krùe+d> ZHe+d0 D ]ZIeH >eeIe+d9 e:e+d0 ƒ d:d?d@¡ qÄe/eHe+d9 eC e+d1 dA d:gd:gg d3¢e6dd; e jE F¡  ne GdEe+d9 › d7¡ dFZJdGd'„ ee4ƒ KdH¡D ƒZLg ZMeDeJƒD ]ZNejOjP )eLejQ Rd e:eLƒ¡ ¡\ZSZTeM Ue: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 r ej, 0ej, 2e7dN¡¡rye%jZdu r›dOd'„ 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 rþd+ZdneddW Zdee\e:e Be3¡ƒe+dK ej, 2e7dN¡e jE e¡ rdXndYe jE e¡ s$ednd+dZ ee`e:e Be5¡ƒe+dK ej, 2e7d[¡e jE e¡ rAdXndYe jE e¡ sJednd+dZ ee^e:e Be4¡ƒe+dK ej, 2e7d\¡e jE e¡ rgdXndYe jE e¡ spednd+dZ eebe:e Be6¡ƒe+dK ej, 2e7d]¡e jE e¡ rdXndYe jE e¡ s–ednd+dZ ne Gd^¡ e%jfdu rejgjdYd_Zheh ie+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rødmdn„ eoeq< qédodn„ eoeq< qée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]¡¡Z‚e ƒe „ejzd  ¡e {e‚jzd  ¡f¡ |ej}¡Z…e jgjsjve jgjs e  €e †ee‚f¡¡e  €e…¡¡e:e…ƒdwZ‡ekjˆewe‡exe+dx e+dy e+dz d{Z‰ekjŠe‰e+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r§t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__© úL/home/kim/smarthome/.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   ZFlattenÚflattenr   Úlayer1r   Úrelu1r   Ú
layernorm1Z
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   )r4   r5   r3   r2   r7   r:   r8   )r   r$   Úblockr!   r!   r"   r%   M   s
   

ú#Model.__init__.<locals>.Net.forward)r   r   r&   r!   ©r+   r   r"   ÚNetB   s    
rB   )r<   r=   Z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ç        )Z
num_layersÚbidirectionalZbatch_firstZdropoutr   r   )
r   r   r   ZLSTMr3   r   Úlayer2r9   r   Úlayer3)r   r;   r=   r   r!   r"   r   V   s   
ÿ$r>   c                 S   s*   |   |¡\}}|  |  |d d …df ¡¡S )NrC   )r3   rI   rH   )r   r$   ÚoutÚhr!   r!   r"   r%   ]   s   r@   ©r   r&   r!   r!   r   r"   rB   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   ©Zaxis©Útorchr   Ú
functionalÚsoftmaxÚargmaxÚmaxrM   )ÚprO   Ú	thresholdÚprobsZ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 rU   rY   )r_   rO   Únegative_class_labelr`   ra   Úpos_ndcsZ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   rV   rX   )rZ   r   r[   r\   r]   rM   )r_   rO   rd   ra   Z	pos_predsÚaccr!   r!   r"   Úpositive_class_accuracyu   s   $z/Model.__init__.<locals>.positive_class_accuracyç-Cëâ6?)Úlr)rT   )r   rT   ©r   )'r   r   r=   r;   Úseconds_per_examplerZ   ÚdeviceÚcudaÚis_availableÚbest_modelsÚbest_model_scoresÚbest_val_fpÚbest_val_accuracyÚbest_val_recallZbest_train_recallr   ÚModuleÚmodelrb   ÚtorchmetricsZRecallÚrecallZAccuracyÚaccuracyrg   Ún_fpÚval_fpÚcollectionsÚdefaultdictÚlistÚhistoryr[   Zbinary_cross_entropyZcross_entropyÚlossr   ZAdamÚ
parametersÚ	optimizer)r   r=   r;   Ú
model_typer   r<   rl   rB   rc   rf   rh   r   rA   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=   rZ   Úsaverv   )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   )Z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   rv   Ú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   rV   )rZ   r   r[   r\   rv   r#   r!   r!   r"   r%       ó   z'Model.export_to_onnx.<locals>.M.forwardr&   r!   ©rŠ   r   r"   ÚM™   s    r   )
r=   rZ   ÚonnxÚexportrv   rˆ   Úrandr;   r   ru   )r   r…   Zclass_mappingr   r!   rŒ   r"   Úexport_to_onnx   s   
 
ÿ

ÿôzModel.export_to_onnxr   rF   çü©ñÒMbP?c           	      C   st   d| dt  t j|| |  t|| | ƒ ¡  }|||  }|dkr/t  ||| k||¡}t  ||k ||¡}|S )NrT   r   r   )ÚnpÚcosÚpiÚfloatÚwhere)	r   Zglobal_stepÚwarmup_stepsÚholdÚtotal_stepsZstart_lrÚ	target_lrZlearning_rateZ	warmup_lrr!   r!   r"   Úlr_warmup_cosine_decay§   s   	
ÿÿzModel.lr_warmup_cosine_decayc                 C   s
   |   |¡S r   ©rv   r#   r!   r!   r"   r%   À   ó   
zModel.forwardc                 C   s   t j| jd| j ddS )NrL   r   )Z
input_sizerm   )Ú	torchinfoÚsummaryrv   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   )rp   ÚcopyÚdeepcopyZ
state_dictÚitemsÚlenZload_state_dict)r   ÚmodelsZaveraged_modelZaveraged_model_dictÚkeyrv   Z
model_dictÚvaluer!   r!   r"   Úaverage_modelsÆ   s   ÿ
zModel.average_modelsçš™™™™™&@rT   çš™™™™™É?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rŠt 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.   rb   )Úval_set_hrsr!   r"   r0   õ   r1   z,Model._select_best_model.<locals>.<listcomp>c                    s   g | ]
\}}|ˆ kr|‘qS r!   r!   )r.   Úndxrb   )Úmax_fp_per_hourr!   r"   r0   ÷   s    c                    s   g | ]	}ˆ j | d  ‘qS )Ú
val_recall)rq   )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¤   rp   rˆ   rm   r   Ú	enumeraterZ   Úno_gradrb   Údetachr   Únumpyr^   ÚloggingÚwarningr“   r]   rq   Úinfo)r   Zfalse_positive_validate_datar¯   r±   Z
min_recallZfalse_positive_ratesÚbatchÚx_valÚy_valZmdl_ndxrv   Úval_psZcandidate_model_ndxZcandidate_model_recallÚ
best_modelZbest_model_training_stepr!   )r±   r   r¯   r"   Ú_select_best_modelá   s4   "ÿ
*þ€þÿþzModel._select_best_modeléPÃ  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| |¡ qåt|ƒ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 s‘w   Y  t  d|› d|› d|› d¡ |S )zìA 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...
##################################################ri   r   g      Ð?é   é   é   )
ÚXÚX_valÚfalse_positive_val_dataÚ	max_stepsÚnegative_weight_scheduleÚ	val_stepsr˜   Ú
hold_stepsrj   r¯   z…##################################################
Starting training sequence 2...
##################################################é
   rE   zCIncreasing weight on negative examples to reduce false positives...z…##################################################
Starting training sequence 3...
##################################################zBMerging checkpoints above the 90th percentile into single model...Úval_accuracyéZ   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“   ZlinspaceÚintÚtolistÚastypeÚint64Útrain_modelrr   Zint16Ú
percentiler   Úziprp   rq   Úappendr¤   r¨   rv   rZ   r¶   rˆ   rm   rx   r·   r   r¸   ry   rb   )r   ÚX_trainrÇ   rÈ   ÚstepsÚmax_negative_weightÚtarget_fp_per_hourr¯   rj   ÚweightsrË   Zaccuracy_percentileZrecall_percentileZfp_percentiler¥   rv   ZscoreZcombined_modelr¼   r$   rO   r¿   Zcombined_model_recallZcombined_model_accuracyZcombined_model_fpr½   r¾   Z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ˆ   rm   r   r6   ÚshaperØ   rZ   Úvstackrv   r·   r   r¸   r“   )r   Úfeaturesrv   Ú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   é   )rm   Úncpur   ©Ú
batch_sizer   )r
   Zembed_clipsrä   rZ   Ú
from_numpy)r   Zclipsrv   Ú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   zˆExporting 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   é   )Zopset_versionN)r=   Ú
ValueErrorr¹   r»   ÚosÚpathÚjoinr¡   r¢   rZ   rŽ   r   rˆ   r   r;   )r   rv   Ú
model_nameÚ
output_dirZmodel_to_saver!   r!   r"   Úexport_model£  s   
 
ÿzModel.export_modeléú   ri   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rÉt |jd ¡|d  }|dk}d||< |d }n| jdkræt |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råd}t|ƒD ]:\}}t ¡ ( |d   | j¡|d   | j¡}} |  |¡}!||  |!| d ¡7 }W d   ƒ n	1 sÌw   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ròt|ƒD ]R\}}t ¡ @ |d   | j¡|d   | j¡}} |  |¡}!|  |!| d ¡ ¡  ¡  ¡ }(|  !|!| d   tj"¡¡})|  |!| d ¡}W d   ƒ n	1 sÇw   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   ZTrainingr«   r®   )r˜   r™   rš   r›   rj   r’   g+‡ÙÎ÷ï?r   r€   rx   rÐ   r   rT   Zpositive_test_clips_recallrÎ   r²   Úval_n_fprC   é2   rÄ   )r´   r÷   r²   rÎ   rÐ   ),rˆ   rm   rv   rZ   ZTensorr   rµ   Úfloat32r‚   Zparam_groupsrœ   Z	zero_gradZsqueezeÚcatr¤   Úonesrß   r=   r€   ZbackwardÚstepr   rØ   r·   r   r¸   rb   rz   rx   r¶   r6   rà   Úanyry   rÔ   r“   rÖ   rp   r¡   r¢   rq   Úgetrt   rs   )*r   rÆ   rÉ   r˜   rÌ   rÇ   rÈ   Zpositive_test_clipsrÊ   rË   rj   r¯   Zaccumulation_stepsZaccumulated_samplesZaccumulated_predictionsZaccumulated_labelsZstep_ndxÚdatar$   rO   Zy_Úgrâ   Zneg_high_lossZpos_high_lossÚwre   r€   rb   r{   Zval_step_ndxr½   r¾   Zval_predictionsrÐ   ÚtpÚfnr¼   r/   rã   r²   Zval_accr!   r!   r"   rÕ   ²  sØ   "
ÿ

6

$

$
"
ý€
(


€ö€
"
û€""ýÿ†zModel.train_model)r   r   r   r   r   N)r‡   )r   r   r   rF   r’   r   )r©   rT   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)ÚprepareZCPU©rm   Ztf_modelz####
Saving tflite mode to 'rí   Úwb)rŽ   Zonnx_tf.backendr  Z
tensorflowÚloadÚtempfileÚTemporaryDirectoryZexport_graphrð   rñ   rò   ZliteZTFLiteConverterZfrom_saved_modelÚconvertr¹   r»   ÚopenÚwrite)Zonnx_model_pathr…   rŽ   r  ÚtfZ
onnx_modelZtf_repZtmp_dirÚ	converterZtflite_modelÚfr!   r!   r"   Úconvert_onnx_to_tflite>  s(   

ÿ
ú	ý
ú	÷	r  Ú__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)r  ÚactionÚdefaultr  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ÚrZpiper_sample_generator_path)Úgenerate_samplesrô   ró   Zpositive_trainZpositive_testZnegative_trainZnegative_testc                 C   s"   g | ]}t  |¡D ]}|j‘q	qS r!   )rð   Úscandirrñ   )r.   Újr/   r!   r!   r"   r0     s   " r0   Ú	rir_pathsZ!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î?Z	n_samplesÚtarget_phraseZ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_sizeZ
file_namesz8Skipping generation of positive clips for training, as ~z already existz‹##################################################
Generating positive clips for testing
##################################################Zn_samples_valr!  )r(  r)  rè   r*  r+  r,  rô   r-  z3Skipping generation of positive clips testing, as ~zŒ##################################################
Generating negative clips for training
##################################################Zcustom_negative_phrasesrª   )Z
input_textÚNZinclude_partial_phraseZ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   r0  r!   r1  r-   r!   r!   r"   r0   ô  r1   Zaugmentation_roundsZaugmentation_batch_size)r3  rè   Zbackground_clip_pathsZ	RIR_pathsc                 C   r0  r!   r1  r-   r!   r!   r"   r0   ú  r1   c                 C   r0  r!   r1  r-   r!   r!   r"   r0      r1   c                 C   r0  r!   r1  r-   r!   r!   r"   r0     r1   z›##################################################
Computing openwakeword features for generated samples
##################################################rE   Zgpur   )Zn_totalZclip_durationÚoutput_filerm   ræ   znegative_features_train.npyzpositive_features_test.npyznegative_features_test.npyzVOpenwakeword features already exist, skipping data augmentation and feature generationr  i€>  rƒ   Z
layer_sizei   )r=   r;   rƒ   r   rl   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à   Úarrayr6   )r$   r6  Z	new_batchr!   r5  r"   r  6  s
   
,ÿr  c                 C   s   i | ]}|t “qS r!   )r  )r.   r¦   r!   r!   r"   Ú
<dictcomp>@  r  r8  Zfeature_data_filesZpositiveZadversarial_negativec                 C   ó   dd„ | D ƒS )Nc                 S   ó   g | ]}d ‘qS rL   r!   r-   r!   r!   r"   r0   D  rQ   ú<lambda>.<locals>.<listcomp>r!   ©r$   r!   r!   r"   rP   D  ó    rP   c                 C   r9  )Nc                 S   r:  rk   r!   r-   r!   r!   r"   r0   F  rQ   r;  r!   r<  r!   r!   r"   rP   F  r=  Zbatch_n_per_class)Zn_per_classZdata_transform_funcsZ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   rA  r!   r!   r!   r"   r>  T  s    r>  )rè   Znum_workersZprefetch_factorZ#false_positive_validation_data_pathc                 C   s    g | ]}t ||td   … ‘qS rk   )ÚX_val_fpr;   r-   r!   r!   r"   r0   d  s     rç   rÚ   rÛ   Ztarget_false_positives_per_hour)rÙ   rÇ   rÈ   rÚ   rÛ   rÜ   )rv   ró   rô   rì   z.tflite)r   )‹rZ   r   r   rŸ   rw   r¡   rð   Úsysr  r%  r¸   r“   Zscipyr|   Úargparser¹   r   ÚyamlÚpathlibr   ZopenwakewordZopenwakeword.datar   r   r   Zopenwakeword.utilsr	   r
   ru   r   r  r'   ÚArgumentParserÚparserÚadd_argumentr2  Ú
parse_argsÚargsr  r  Ztraining_configÚreadÚLoaderÚconfigrñ   ÚinsertÚabspathr  ÚexistsÚmkdirrò   Zpositive_train_output_dirZpositive_test_output_dirZnegative_train_output_dirZnegative_test_output_dirZfeature_save_dirr  r  r¤   r×   Zbackground_pathZduplication_rateÚextendr  Zgenerate_clipsr»   ÚlistdirZn_current_samplesr6   rn   Zempty_cacherº   Zadversarial_textsr   r6  ÚglobZpositive_clipsZduration_in_samplesr/   ÚioZwavfileÚrandomÚrandintÚsrZdatrØ   rÑ   ÚroundZmedianÚabsÚ	overwriteZpositive_clips_trainZpositive_clips_train_generatorZpositive_clips_testZpositive_clips_test_generatorZnegative_clips_trainZnegative_clips_train_generatorZnegative_clips_testZnegative_clips_test_generatorÚ	cpu_countZn_cpusro   rÕ   Úutilsrê   Zget_embedding_shaper;   Zowwr  ÚkeysZdata_transformsZlabel_transformsr~   r¦   Zbatch_generatorrÿ   ZIterableDatasetr>  Z
DataLoaderrÙ   rB  r7  rß   ZzerosrÓ   rù   ZX_val_fp_labelsZTensorDatasetré   Z	X_val_posZ	X_val_negZhstackrû   Úlabelsrà   rÇ   rÞ   rÀ   rõ   r!   r!   r!   r"   Ú<module>   s2       )
üûûûû "

û

ý

ü
ü

ü
ý$"
$ 
ý 
ý 
ý 
ý

üüüü
ÿ

 
ü
ÿ*þ.þû	ú
ÿ  Í [