How to use start_step method in Lemoncheesecake

Best Python code snippet using lemoncheesecake

pruned_model.py

Source:pruned_model.py Github

copy

Full Screen

1import tensorflow as tf2from tensorflow import keras3from tensorflow.python.keras.engine.base_layer import Layer4from tensorflow.keras.preprocessing.image import ImageDataGenerator5import numpy as np6import os7import cv28from tensorflow.python.framework import ops9from tensorflow.python.ops import math_ops10import tensorflow_model_optimization as tfmot11from tensorflow.keras.callbacks import TensorBoard12from tensorflow_model_optimization.python.core.sparsity.keras import pruning_wrapper13from tensorflow_model_optimization.python.core.quantization.keras import quantize_annotate14#tf.config.list_physical_devices('GPU')15# mish Activation16class Mish(Layer):17 '''18 Mish Activation Function.19 Examples:20 >>> X_input = Input(input_shape)21 >>> X = Mish()(X_input)22 '''23 def __init__(self, **kwargs):24 super(Mish, self).__init__(**kwargs)25 self.supports_masking = True26 def call(self, inputs):27 return inputs * keras.backend.tanh(keras.backend.log(keras.backend.exp(inputs)+1))28 def get_config(self):29 base_config = super(Mish, self).get_config()30 return {**base_config}31 def compute_output_shape(self, input_shape):32 return input_shape33class Sigmoid(Layer):34 def __init__(self, **kwargs):35 super(Sigmoid, self).__init__(**kwargs)36 self.supports_masking = True37 def call(self, inputs):38 return keras.backend.sigmoid(inputs)39 def get_config(self):40 base_config = super(Sigmoid, self).get_config()41 return {**base_config}42 def compute_output_shape(self, input_shape):43 return input_shape44# customize DNN modules45def backbone(input, start_step, end_step, prune, decay):46 conv = keras.layers.Conv2D(16, (3, 3), strides=(2, 2), padding='same')(input)47 bn = keras.layers.BatchNormalization(axis=-1, momentum=0.9)(conv)48 act = Mish()(bn)49 res = prune(keras.layers.Conv2D(16, (1, 1), strides=(2, 2), padding='same'), decay(0.02, 0.08, start_step, end_step))(act)50 bn_res = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.05, 0.15, start_step, end_step))(res)51 act_res = Mish()(bn_res)52 dws = prune(keras.layers.SeparableConv2D(16, (3, 3), padding='same'), decay(0.02, 0.08, start_step, end_step))(act)53 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.05, 0.15, start_step, end_step))(dws)54 act = Mish()(bn)55 dws = prune(keras.layers.SeparableConv2D(16, (3, 3), padding='same'), decay(0.05, 0.15, start_step, end_step))(act)56 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.1, 0.2, start_step, end_step))(dws)57 act = Mish()(bn)58 mp = keras.layers.MaxPooling2D((3, 3), strides=2, padding='same')(act)59 mp = keras.layers.add([mp, act_res])60 mp = Mish()(mp)61 conv = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(mp)62 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv)63 act = Mish()(bn)64 conv = prune(keras.layers.Conv2D(64, (3, 3), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(bn)65 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv)66 act = Mish()(bn)67 conv_1 = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(mp)68 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv_1)69 act_1 = Mish()(bn_1)70 conv_1 = prune(keras.layers.Conv2D(32, (5, 1), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(act_1)71 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv_1)72 act_1 = Mish()(bn_1)73 conv_1 = prune(keras.layers.Conv2D(32, (1, 5), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(act_1)74 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv_1)75 act_1 = Mish()(bn_1)76 conv_1 = prune(keras.layers.Conv2D(64, (3, 3), strides=1, padding='same'), decay(0.15, 0.3, start_step, end_step))(act_1)77 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.2, 0.4, start_step, end_step))(conv_1)78 act_1 = Mish()(bn_1)79 concat = tf.keras.layers.concatenate(inputs=[act, act_1], axis=3)80 return concat81def neck_module1(ip, start_step, end_step, prune, decay):82 input = Mish()(ip)83 conv = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.2, 0.4, start_step, end_step))(input)84 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.4, 0.6, start_step, end_step))(conv)85 act = Mish()(bn)86 conv = prune(keras.layers.Conv2D(64, (1, 3), strides=1, padding='same'), decay(0.2, 0.4, start_step, end_step))(act)87 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.4, 0.6, start_step, end_step))(conv)88 act = Mish()(bn)89 conv = prune(keras.layers.Conv2D(32, (3, 1), strides=1, padding='same'), decay(0.2, 0.4, start_step, end_step))(act)90 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.4, 0.6, start_step, end_step))(conv)91 act = Mish()(bn)92 conv_1 = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(input)93 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_1)94 act_1 = Mish()(bn_1)95 conv_1 = prune(keras.layers.Conv2D(64, (1, 3), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(act_1)96 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_1)97 act_1 = Mish()(bn_1)98 conv_1 = prune(keras.layers.Conv2D(64, (3, 1), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(act_1)99 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_1)100 act_1 = Mish()(bn_1)101 conv_1 = prune(keras.layers.Conv2D(64, (1, 3), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(act_1)102 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_1)103 act_1 = Mish()(bn_1)104 conv_1 = prune(keras.layers.Conv2D(32, (3, 1), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(act_1)105 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_1)106 act_1 = Mish()(bn_1)107 mp = keras.layers.MaxPooling2D((2, 2), strides=1, padding='same')(input)108 conv_2 = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(mp)109 bn_2 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_2)110 act_2 = Mish()(bn_2)111 conv_3 = prune(keras.layers.Conv2D(32, (1, 1), strides=1, padding='same'), decay(0.3, 0.5, start_step, end_step))(input)112 bn_3 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.5, 0.7, start_step, end_step))(conv_3)113 act_3 = Mish()(bn_3)114 concat = keras.layers.concatenate(inputs=[act, act_1, act_2, act_3], axis=3)115 sum = keras.layers.add([concat, input])116 return sum117def neck_module2(ip, start_step, end_step, prune, decay):118 input = Mish()(ip)119 dws = prune(keras.layers.SeparableConv2D(64, (3, 3), padding='same'), decay(0.4, 0.7, start_step, end_step))(input)120 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.6, 0.8, start_step, end_step))(dws)121 act = Mish()(bn)122 dws = prune(keras.layers.SeparableConv2D(128, (3, 3), padding='same'), decay(0.4, 0.7, start_step, end_step))(act)123 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.6, 0.8, start_step, end_step))(dws)124 act = Mish()(bn)125 dws = prune(keras.layers.SeparableConv2D(192, (3, 3), padding='same'), decay(0.4, 0.7, start_step, end_step))(act)126 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.6, 0.8, start_step, end_step))(dws)127 act = Mish()(bn)128 dws_c = prune(keras.layers.SeparableConv2D(64, (3, 3), padding='same'), decay(0.4, 0.7, start_step, end_step))(input)129 bn_c = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.6, 0.8, start_step, end_step))(dws_c)130 act_c = Mish()(bn_c)131 concat = keras.layers.concatenate(inputs=[input, act_c], axis=3)132 sum = keras.layers.add([concat, act])133 act_sum = Mish()(sum)134 mp = keras.layers.MaxPooling2D((3, 3), strides=2, padding='same')(act_sum)135 conv = prune(keras.layers.Conv2D(128, (1, 1), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(mp)136 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv)137 act = Mish()(bn)138 conv = prune(keras.layers.Conv2D(128, (1, 3), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act)139 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv)140 act = Mish()(bn)141 conv = prune(keras.layers.Conv2D(256, (3, 1), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act)142 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv)143 act = Mish()(bn)144 conv_01 = prune(keras.layers.Conv2D(96, (1, 3), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act)145 bn_01 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv_01)146 act_01 = Mish()(bn_01)147 conv_02 = prune(keras.layers.Conv2D(96, (3, 1), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act)148 bn_02 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv_02)149 act_02 = Mish()(bn_02)150 conv_1 = prune(keras.layers.Conv2D(192, (1, 1), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(mp)151 bn_1 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv_1)152 act_1 = Mish()(bn_1)153 conv_11 = prune(keras.layers.Conv2D(96, (1, 3), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act_1)154 bn_11 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv_11)155 act_11 = Mish()(bn_11)156 conv_12 = prune(keras.layers.Conv2D(96, (3, 1), strides=1, padding='same'), decay(0.6, 0.8, start_step, end_step))(act_1)157 bn_12 = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, start_step, end_step))(conv_12)158 act_12 = Mish()(bn_12)159 concat_1 = keras.layers.concatenate(inputs=[act_01, act_02], axis=3)160 concat_2 = keras.layers.concatenate(inputs=[act_11, act_12], axis=3)161 sum = keras.layers.add([mp, concat_1, concat_2])162 return sum163def head(ip, start_step, end_step, prune, decay):164 input = Mish()(ip)165 dws = prune(keras.layers.SeparableConv2D(256, (3, 3), padding='same'), decay(0.7, 0.9, 0, end_step))(input)166 bn_dws = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, 0, end_step))(dws)167 act_dws = Mish()(bn_dws)168 dws = prune(keras.layers.SeparableConv2D(384, (3, 3), padding='same'), decay(0.7, 0.9, 0, end_step))(act_dws)169 bn_dws = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, 0, end_step))(dws)170 act_dws = Mish()(bn_dws)171 conv = prune(keras.layers.Conv2D(384, (1, 1), strides=1, padding='same'), decay(0.7, 0.9, 0, end_step))(input)172 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, 0, end_step))(conv)173 act = Mish()(bn)174 sum = keras.layers.add([act, act_dws])175 act_sum = Mish()(sum)176 dws = prune(keras.layers.SeparableConv2D(512, (3, 3), padding='same'), decay(0.7, 0.9, 0, end_step))(act_sum)177 bn = prune(keras.layers.BatchNormalization(axis=-1, momentum=0.9), decay(0.8, 0.9, 0, end_step))(dws)178 act = Mish()(bn)179 gap = keras.layers.GlobalAveragePooling2D()(act)180 return gap181def FADNet(input_shape, start_step, end_step, prune, decay):182 img_input = keras.layers.Input(shape=input_shape)183 bb = backbone(img_input, start_step, end_step, prune, decay)184 mp0 = keras.layers.MaxPooling2D((3, 3), strides=2, padding='same')(bb)185 n1 = neck_module1(mp0, start_step, end_step, prune, decay)186 mp1 = keras.layers.MaxPooling2D((3, 3), strides=2, padding='same')(n1)187 n2 = neck_module2(mp1, start_step, end_step, prune, decay)188 mp2 = keras.layers.MaxPooling2D((3, 3), strides=2, padding='same')(n2)189 h = head(mp2, start_step, end_step, prune, decay)190 d2 = prune(keras.layers.Dense(1), decay(0.7, 0.9, start_step, end_step))(h)191 d2 = Sigmoid()(d2)192 model = tf.keras.Model(img_input, d2)193 return model194# Customize early stopping callback195class MyThresholdCallback(tf.keras.callbacks.Callback):196 def __init__(self, tr_threshold, val_threshold):197 super(MyThresholdCallback, self).__init__()198 self.tr_threshold = tr_threshold199 self.val_threshold = val_threshold200 def on_epoch_end(self, epoch, logs=None):201 val_acc = logs["val_accuracy"]202 tr_acc = logs["accuracy"]203 if val_acc >= self.val_threshold or tr_acc >= self.tr_threshold:204 self.model.stop_training = True205# Customize learning rate schedule206class CustomSchedule(tf.keras.optimizers.schedules.LearningRateSchedule):207 def __init__(self, initial_learning_rate, decay_steps, decay_rate, warmup_steps):208 super(CustomSchedule, self).__init__()209 self.initial_learning_rate = initial_learning_rate210 self.decay_steps = decay_steps211 self.decay_rate = decay_rate212 self.warmup_steps = warmup_steps213 def __call__(self, step):214 arg1 = self.initial_learning_rate * (self.decay_rate**((step-self.warmup_steps)/self.decay_steps))215 arg2 = self.initial_learning_rate * step / self.warmup_steps216 return tf.math.minimum(arg1, arg2)217 def get_config(self):218 return {219 "initial_learning_rate": self.initial_learning_rate,220 "decay_steps": self.decay_steps,221 "decay_rate": self.decay_rate,222 "warmup_steps": self.warmup_steps,223 }224def blur(img):225 return (cv2.blur(img,(5,5)))226def main():227 # Start k-fold cross vailidation228 k = 6229 val_acc = 0230 val_loss = 0231 model = None232 select = 1233 # Uncomment this to visualize an example of the learn rate schedule234 # temp_learning_rate_schedule = CustomSchedule(initial_learning_rate=0.001*0.95**50, decay_steps=584, decay_rate=0.95, warmup_steps=0)235 # plt.plot(temp_learning_rate_schedule(tf.range(40000, dtype=tf.float32)))236 # plt.ylabel("Learning Rate")237 # plt.xlabel("Train Step")238 # plt.show()239 fill_modes = ["constant", "reflect", "nearest"]240 rr = [10.0, 15.0, 10.0]241 sr = [10.0, 20.0, 10.0]242 cval = [np.random.random()*255, 0, 0]243 for i in range(3):244 # prefix = 'ks\\k' + str(i) + '\\'245 prefix = 'dataset/'246 # img_width, img_height = 100, 100247 train_data_dir = prefix + 'train/'248 validation_data_dir = prefix + 'test/'249 epochs = 30250 batch_size = 30251 if select == 0:252 select = 1253 elif select == 1:254 select = 2255 elif select == 2:256 select = 0257 print(fill_modes[select])258 # Generate Tensor for input images259 train_datagen = ImageDataGenerator(260 rescale=1. / 255,261 width_shift_range=0.2,262 height_shift_range=0.2,263 brightness_range=(0.7, 1.2),264 rotation_range=rr[select],265 shear_range=sr[select],266 zoom_range=(0.8, 1.3),267 channel_shift_range=60,268 fill_mode = fill_modes[select],269 cval=cval[select],270 horizontal_flip=True,271 vertical_flip=True)272 test_datagen = ImageDataGenerator(rescale=1. / 255,273 brightness_range=(0.9, 1.1),274 zoom_range=(1.0, 1.2),275 channel_shift_range=30,276 horizontal_flip=True)277 # Generate Iterator flow from directory278 train_generator = train_datagen.flow_from_directory(279 train_data_dir,280 # target_size=(img_width, img_height),281 target_size=(320, 320),282 batch_size=batch_size,283 class_mode='binary')284 validation_generator = test_datagen.flow_from_directory(285 validation_data_dir,286 # target_size=(img_width, img_height),287 target_size=(320, 320),288 batch_size=batch_size,289 class_mode='binary')290 # Get input image dimension291 unit_image = train_generator.next()[0]292 shape = (unit_image.shape[1], unit_image.shape[2], unit_image.shape[3])293 # pruning specifications294 poly_decay = tfmot.sparsity.keras.PolynomialDecay295 prune = tfmot.sparsity.keras.prune_low_magnitude296 start_step = 101297 end_step = int(584 * epochs / 2)298 quantize_annotate_layer = tfmot.quantization.keras.quantize_annotate_layer299 quantize_annotate_model = tfmot.quantization.keras.quantize_annotate_model300 quantize_scope = tfmot.quantization.keras.quantize_scope301 # Pruned DNN302 pruned_model = FADNet(shape, start_step, end_step, prune, poly_decay)303 # BP304 decay_exp = 0305 if i > 0:306 decay_exp = 60307 # if i == 5:308 # th = 0.985309 lr_schedule = CustomSchedule(initial_learning_rate=0.0001*(0.98**decay_exp)/(i+1),310 decay_steps=584,311 decay_rate=0.95,312 warmup_steps=584*int((i+1)/2))313 opt = keras.optimizers.Adam(learning_rate=lr_schedule, clipnorm=5)314 bcel = keras.losses.BinaryCrossentropy(label_smoothing=0.1)315 # check for transfer learning316 if os.path.exists("quantized_model.h5"):317 pruned_model.load_weights("quantized_model.h5", by_name=True)318 print(pruned_model.layers[-2].get_weights()[0])319 print("Transfer learning continued")320 pruned_model.summary()321 pruned_model.compile(optimizer=opt, loss=bcel, metrics=['accuracy'])322 # callbacks323 my_callbacks = [324 tfmot.sparsity.keras.UpdatePruningStep(),325 # tfmot.sparsity.keras.PruningSummaries(log_dir='pruned_model'),326 keras.callbacks.EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True),327 MyThresholdCallback(tr_threshold=0.99, val_threshold=0.992+0.001*i),328 # TensorBoard(log_dir="prune"+str(i),329 # histogram_freq=0,330 # write_graph=True,331 # write_images=False,332 # update_freq="epoch",333 # profile_batch=2),334 keras.callbacks.ModelCheckpoint(filepath='pruned_model.h5',335 save_weights_only=False,336 monitor='val_loss',337 mode='min',338 save_best_only=True)339 ]340 history = pruned_model.fit(train_generator, epochs=epochs, validation_data=validation_generator, callbacks=my_callbacks)341 # visualize compression342 # _, pruned_keras_file = tempfile.mkstemp('.h5')343 # tf.keras.models.save_model(model_for_export, pruned_keras_file, include_optimizer=False)344 # print("Size of gzipped pruned Keras model: %.2f bytes" % (get_gzipped_model_size(pruned_keras_file)))345 print('Finished part ' + str(i + 1))346 # strip pruning layers for final model347 model_for_export = tfmot.sparsity.keras.strip_pruning(pruned_model)348 model_for_export.save("pruned_model_stripped.h5")349 model_for_export.save_weights("pruned_model_weights.h5")350if __name__ == '__main__':...

Full Screen

Full Screen

trapping_water.py

Source:trapping_water.py Github

copy

Full Screen

1class Solution:2 def trap(self, height):3 if len(height) < 3:4 return []5 my_trap = []6 start_step = 07 while start_step <= len(height) - 3:8 if height[start_step] > height[start_step + 1]:9 j = start_step + 110 trap_sequence = []11 trap_sequence.append(height[start_step])12 while j < len(height) -1 and height[j] < height[start_step]:13 trap_sequence.append(height[j])14 j += 115 if height[j] >= height[start_step]:16 trap_sequence.append(height[j])17 else:18 trap_sequence = []19 if len(trap_sequence) > 0:20 my_trap.append(trap_sequence)21 start_step = j22 else:23 start_step +=124 return self.calculate(my_trap)25 def calculate(self, trap):26 trapped_water = 027 for trap_sequence in trap:28 sum = 029 mark_heigh = trap_sequence[0]30 for j in trap_sequence:31 sum += max(mark_heigh - j, 0)32 trapped_water += sum33 return trapped_water34if __name__ == '__main__':35 s = Solution()...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Lemoncheesecake automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful