نجعل تصنيف المدن الروسية حسب جودة الطرق



مرة أخرى ، عندما كنت أقود سيارة حول مدينتي وأتجول في حفرة أخرى ، اعتقدت: هل توجد مثل هذه الطرق "الجيدة" في كل مكان في بلدنا وقررت أنه ينبغي لنا تقييم الوضع بموضوعية بجودة الطرق في بلدنا.

إضفاء الطابع الرسمي على المهمة


في روسيا ، تم توضيح متطلبات جودة الطرق في GOST R 50597-2017 "الطرق والطرق. متطلبات الحالة التشغيلية مقبولة بموجب شروط ضمان السلامة على الطرق. طرق التحكم. " تحدد هذه الوثيقة متطلبات تغطية الطريق ، جوانب الطرق ، شرائط التقسيم ، الأرصفة ، ممرات المشاة ، وما إلى ذلك ، كما تحدد أنواع الضرر.

نظرًا لأن مهمة تحديد جميع معالم الطرق مهمة للغاية ، فقد قررت تضييقها بنفسي والتركيز فقط على مشكلة تحديد العيوب في تغطية الطريق. في GOST R 50597-2017 ، يتم تمييز العيوب التالية في طلاء الطريق:

  • الحفر
  • فواصل
  • السحب
  • التحولات
  • أمشاط
  • المسار
  • التعرق الموثق

قررت معالجة هذه العيوب.

جمع البيانات


أين يمكنني الحصول على صور توضح أجزاء كبيرة بما يكفي من الطريق ، وحتى بالإشارة إلى تحديد الموقع الجغرافي؟ جاءت الإجابة في أحجار الراين - صور بانورامية على خرائط Yandex (أو Google) ، ومع ذلك ، بعد قليل من البحث ، وجدت العديد من الخيارات البديلة:

  • إصدار محركات البحث عن الصور للطلبات ذات الصلة ؛
  • الصور على مواقع لتلقي الشكاوى (Rosyama ، المواطن الغاضب ، الفضيلة ، إلخ.)
  • دفع Opendatascience مشروعًا لاكتشاف عيوب الطرق باستخدام مجموعة بيانات ملحوظة - github.com/sekilab/RoadDamageDetector

لسوء الحظ ، أظهر تحليل لهذه الخيارات أنها ليست مناسبة جدًا بالنسبة لي: إصدار محركات البحث لديه الكثير من الضوضاء (العديد من الصور التي ليست طرقًا أو عروض مختلفة أو ما إلى ذلك) ، والصور من مواقع تلقي الشكاوى تحتوي فقط على صور بها انتهاكات كبيرة لسطح الأسفلت ، هناك عدد غير قليل من الصور مع انتهاكات صغيرة للتغطية وبدون انتهاكات على هذه المواقع ، يتم جمع مجموعة البيانات من مشروع RoadDamageDetector في اليابان ولا تحتوي على عينات ذات انتهاكات كبيرة للتغطية ، وكذلك الطرق دون تغطية على الإطلاق.

نظرًا لأن الخيارات البديلة غير مناسبة ، فسنستخدم بانوراما Yandex (لقد استبعدت خيار بانوراما Google ، نظرًا لأن الخدمة مقدمة في عدد أقل من المدن في روسيا ويتم تحديثها بشكل أقل تكرارًا). قرر جمع البيانات في المدن التي يبلغ عدد سكانها أكثر من 100 ألف شخص ، وكذلك في المراكز الفيدرالية. لقد قدمت قائمة بأسماء المدن - كان هناك 176 منهم ، فيما بعد تبين أن 149 منهم فقط لديهم صور بانورامية. لن أتطرق إلى ميزات تحليل البلاط ، سأقول أنه في النهاية حصلت على 149 مجلدًا (مجلد لكل مدينة) بلغ إجمالي عدد الصور بها 1.7 مليون صورة. على سبيل المثال ، بالنسبة إلى Novokuznetsk ، بدا المجلد كما يلي:



بعدد الصور التي تم تنزيلها ، تم توزيع المدن على النحو التالي:

الجدول
المدينة
عدد الصور ، أجهزة الكمبيوتر
موسكو

86048

سانت بطرسبرغ

41376

سارانسك

18880

بودولسك

18560

كراسنوجورسك

18208

ليوبرتسي

17760

كالينينجراد

16928

Kolomna

16832

ميتيشتشي

16192

فلاديفوستوك

16096

بالشيخة

15968

بتروزافودسك

15968

ايكاترينبرغ

15808

فيليكي نوفغورود

15744

نابريجني تشلني

15680

كراسنودار

15520

نيجني نوفغورود

15488

خيمكي

15296

تولا

15296

نوفوسيبيرسك

15264

تفير

15200

مياس

15104

إيفانوفو

15072

فولوغدا

15008

جوكوفسكي

14976

كوستروما

14912

سمارة

14880

كوروليف

14784

كالوغا

14720

تشيريبوفيتس

14720

سيفاستوبول

14688

بوشكينو

14528

ياروسلافل

14464

أوليانوفسك

14400

روستوف نا دون

14368

دوموديدوفو

14304

كامينسك-أورالسكي

14208

بسكوف

14144

يوشكار علا

14080

كيرتش

14080

مورمانسك

13920

توجلياتي

13920

فلاديمير

13792

النسر

13792

سيكتيفكار

13728

دولجوبرودني

13696

خانتي مانسيسك

13664

قازان

13600

إنجلز

13440

أرخانجيلسك

13280

بريانسك

13216

أومسك

13120

سيزران

13088

كراسنويارسك

13056

شيلكوفو

12928

بينزا

12864

تشيليابينسك

12768

تشيبوكساري

12768

نيجني تاجيل

12672

ستافروبول

12672

رامينسكوي

12640

ايركوتسك

12608

أنجارسك

12608

تيومين

12512

أودينتسوفو

12512

أوفا

12512

ماجادان

12512

بيرم

12448

كيروف

12256

نيجنكامسك

12224

مخاشكالا

12096

نيجنفارتوفسك

11936

كورسك

11904

سوتشي

11872

تامبوف

11840

بياتيغورسك

11808

فولجودونسك

11712

ريازان

11680

ساراتوف

11616

دزيرنسك

11456

أورينبورغ

11456

تل

11424

فولجوجراد

11264

إيجيفسك

11168

كريسوستوم

11136

ليبيتسك

11072

كيسلوفودسك

11072

سورجوت

11040

ماغنيتيوغورسك

10912

سمولينسك

10784

خاباروفسك

10752

كوبيسك

10688

مايكوب

10656

بيتروبافلوفسك كامتشاتسكي

10624

تاغونروغ

10560

بارناول

10528

سيرجيف بوساد

10368

إليستا

10304

سترليتاماك

9920

سيمفيروبول

9824

تومسك

9760

أوريخوفو زويفو

9728

استراخان

9664

يوباتوريا

9568

نوجينسك

9344

تشيتا

9216

بيلغورود

9120

Biysk

8928

ريبينسك

8896

سيفيرودفينسك

8832

فورونيج

8768

بلاغوفيشتشينسك

8672

نوفوروسيسك

8608

أولان أودي

8576

سيربوخوف

8320

كومسومولسك أون أمور

8192

أباكان

8128

نوريلسك

8096

يوجنو ساخالينسك

8032

أوبينسك

7904

إسنتوكي

7712

باتايسك

7648

فولجسكي

7584

نوفوتشركاسك

7488

بيردسك

7456

أرزاماس

7424

بيرفورالسك

7392

كيميروفو

7104

إلكتروستال

6720

ديربنت

6592

ياكوتسك

6528

موروم

6240

نفتيوجانسك

5792

ريوتوف

5696

بيروبيجان

5440

نوفوكويبيشيفسك

5248

سالخارد

5184

نوفوكوزنيتسك

5152

نوفي يورنغوي

4736

نويابرسك

4416

نوفوتشيبوكسارسك

4352

الصراصير

3968

كاسبييسك

3936

ستاري اوسكول

3840

أرتيوم

3744

زيليزنوغورسك

3584

Salavat

3584

بروكوبيفسك

2816

غورنو التايسك

2464



إعداد مجموعة بيانات للتدريب


وهكذا ، يتم تجميع مجموعة البيانات ، فكيف الآن ، وبعد الحصول على صورة لقسم الطريق والأشياء المجاورة ، اكتشف نوعية الإسفلت المبين عليها؟ قررت قطع جزء من الصورة بقياس 350 * 244 بكسل في وسط الصورة الأصلية أسفل الوسط مباشرة. ثم قم بتقليل القطعة المقطوعة أفقياً إلى حجم 244 بكسل. ستكون الصورة الناتجة (244 * 244 في الحجم) هي مدخلات المشفر التلافيفي:



من أجل فهم أفضل للبيانات التي أتعامل معها ، أول 2000 صورة قمت بتمييزها بنفسي ، تم تمييز بقية الصور بواسطة موظفي Yandex.Tolki. أمامهم طرحت سؤالا في الصياغة التالية.

أشر إلى سطح الطريق الذي تراه في الصورة:

  1. التربة / الأنقاض
  2. رصف الحجارة والبلاط والرصيف
  3. القضبان ، مسارات السكك الحديدية
  4. المياه ، برك كبيرة
  5. الأسفلت
  6. لا يوجد طريق في الصورة / أشياء غريبة / التغطية غير مرئية بسبب السيارات

إذا اختار المؤدي "Asphalt" ، فقد ظهرت قائمة تقدم لتقييم جودتها:

  1. تغطية ممتازة
  2. طفيف الشقوق واحد / الحفر واحد الضحلة
  3. الشقوق الكبيرة / الشقوق الشبكة / الحفر الصغيرة
  4. الحفر الكبيرة / الحفر العميقة / الطلاء المدمر

كما أظهر اختبار المهام ، فإن فناني Y. Toloki لا يختلفون في سلامة العمل - فهم ينقرون عن طريق الخطأ على الحقول باستخدام الماوس وينظرون في المهمة المكتملة. اضطررت إلى إضافة أسئلة تحكم (في المهمة كانت هناك 46 صورة ، منها 12 كانت مراقبة) وتمكين التأخير في القبول. بصفتي أسئلة تحكم ، استخدمت تلك الصور التي حددتها بنفسي. قمت تلقائيًا بالتأخير في القبول - Y. Toloka يسمح لك بتحميل نتائج العمل إلى ملف CSV ، وتحميل نتائج التحقق من الردود. تم التحقق من الإجابات على النحو التالي - إذا كانت المهمة تحتوي على أكثر من 5٪ إجابات غير صحيحة للتحكم في الأسئلة ، فسيتم اعتبارها غير مستوفاة. علاوة على ذلك ، إذا أشار المقاول إلى إجابة قريبة منطقياً من true ، فإن إجابته تعتبر صحيحة.
نتيجةً لذلك ، حصلت على حوالي 30 ألف صورة تحمل علامات ، والتي قررت توزيعها في ثلاثة فصول للتدريب:

  • "جيد" - الصور المصنفة "الإسفلت: طلاء ممتاز" و "الأسفلت: الشقوق المفردة الصغيرة"
  • "الأوسط" - صور تحمل علامات "حجارة الرصف ، والبلاط ، والرصيف" ، و "القضبان ، ومسارات السكك الحديدية" و "الأسفلت: شقوق كبيرة / شقوق الشبكة / الحفر الصغيرة المفردة"
  • "كبير" - الصور التي تحمل علامات "التربة / الأحجار المكسرة" و "المياه والبرك الكبيرة" و "الأسفلت: عدد كبير من الحفر / الحفر العميقة / الرصيف المدمر"
  • الصور الموسومة "لا يوجد طريق في الصورة / الأجسام الغريبة / التغطية غير مرئية بسبب السيارات" كان هناك عدد قليل جدًا (22 قطعة). لقد استثنيتهم ​​من العمل الإضافي

تطوير المصنف والتدريب


لذلك ، يتم جمع البيانات وتصنيفها ، نواصل تطوير المصنف. عادة ، بالنسبة لمهام تصنيف الصور ، خاصة عند التدريب على مجموعات البيانات الصغيرة ، يتم استخدام برنامج تشفير تلافيفي جاهز ، لإخراج مصنف جديد متصل به. قررت استخدام مصنف بسيط بدون طبقة مخفية ، وطبقة إدخال بحجم 128 وطبقة إخراج بحجم 3. قررت استخدام خيارات متعددة جاهزة على الفور تم تدريبها على ImageNet كمشفرات:

  • Xception
  • Resnet
  • التأسيس
  • Vgg16
  • Densenet121
  • Mobilenet

فيما يلي الوظيفة التي تنشئ نموذج Keras باستخدام المشفر المحدد:

def createModel(typeModel): conv_base = None if(typeModel == "nasnet"): conv_base = keras.applications.nasnet.NASNetMobile(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "xception"): conv_base = keras.applications.xception.Xception(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "resnet"): conv_base = keras.applications.resnet50.ResNet50(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "inception"): conv_base = keras.applications.inception_v3.InceptionV3(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "densenet121"): conv_base = keras.applications.densenet.DenseNet121(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "mobilenet"): conv_base = keras.applications.mobilenet_v2.MobileNetV2(include_top=False, input_shape=(224,224,3), weights='imagenet') if(typeModel == "vgg16"): conv_base = keras.applications.vgg16.VGG16(include_top=False, input_shape=(224,224,3), weights='imagenet') conv_base.trainable = False model = Sequential() model.add(conv_base) model.add(Flatten()) model.add(Dense(128, activation='relu', kernel_regularizer=regularizers.l2(0.0002))) model.add(Dropout(0.3)) model.add(Dense(3, activation='softmax')) model.compile(optimizer=keras.optimizers.Adam(lr=1e-4), loss='binary_crossentropy', metrics=['accuracy']) return model 

للتدريب ، استخدمت مولدًا مع زيادة (نظرًا لأن إمكانيات التعزيز المدمجة في Keras بدت لي غير كافية ، ثم استخدمت مكتبة Augmentor ):

  • المنحدرات
  • تشويه عشوائي
  • يتحول
  • مبادلة اللون
  • التحولات
  • تغيير التباين والسطوع
  • مضيفا ضوضاء عشوائية
  • المحاصيل

بعد التكبير ، تبدو الصور كما يلي:



رمز المولد:

 def get_datagen(): train_dir='~/data/train_img' test_dir='~/data/test_img' testDataGen = ImageDataGenerator(rescale=1. / 255) train_generator = datagen.flow_from_directory( train_dir, target_size=img_size, batch_size=16, class_mode='categorical') p = Augmentor.Pipeline(train_dir) p.skew(probability=0.9) p.random_distortion(probability=0.9,grid_width=3,grid_height=3,magnitude=8) p.rotate(probability=0.9, max_left_rotation=5, max_right_rotation=5) p.random_color(probability=0.7, min_factor=0.8, max_factor=1) p.flip_left_right(probability=0.7) p.random_brightness(probability=0.7, min_factor=0.8, max_factor=1.2) p.random_contrast(probability=0.5, min_factor=0.9, max_factor=1) p.random_erasing(probability=1,rectangle_area=0.2) p.crop_by_size(probability=1, width=244, height=244, centre=True) train_generator = keras_generator(p,batch_size=16) test_generator = testDataGen.flow_from_directory( test_dir, target_size=img_size, batch_size=32, class_mode='categorical') return (train_generator, test_generator) 

يُظهر الرمز أن التعزيز لا يستخدم لبيانات الاختبار.

بوجود مولد مُولِّف ، يمكنك البدء في تدريب النموذج ، وسوف نقوم بتنفيذه على مرحلتين: أولاً ، قم بتدريب المصنف الخاص بنا فقط ، ثم النموذج بالكامل بالكامل.

 def evalModelstep1(typeModel): K.clear_session() gc.collect() model=createModel(typeModel) traiGen,testGen=getDatagen() model.fit_generator(generator=traiGen, epochs=4, steps_per_epoch=30000/16, validation_steps=len(testGen), validation_data=testGen, ) return model def evalModelstep2(model): early_stopping_callback = EarlyStopping(monitor='val_loss', patience=3) model.layers[0].trainable=True model.trainable=True model.compile(optimizer=keras.optimizers.Adam(lr=1e-5), loss='binary_crossentropy', metrics=['accuracy']) traiGen,testGen=getDatagen() model.fit_generator(generator=traiGen, epochs=25, steps_per_epoch=30000/16, validation_steps=len(testGen), validation_data=testGen, callbacks=[early_stopping_callback] ) return model def full_fit(): model_names=[ "xception", "resnet", "inception", "vgg16", "densenet121", "mobilenet" ] for model_name in model_names: print("#########################################") print("#########################################") print("#########################################") print(model_name) print("#########################################") print("#########################################") print("#########################################") model = evalModelstep1(model_name) model = evalModelstep2(model) model.save("~/data/models/model_new_"+str(model_name)+".h5") 

استدعاء full_fit () وانتظر. نحن ننتظر لفترة طويلة.

نتيجة لذلك ، سيكون لدينا ستة نماذج مدربة ، وسوف نتحقق من دقة هذه النماذج في جزء منفصل من البيانات ذات العلامات ؛ تلقيت ما يلي:

اسم النموذج


دقة ٪


Xception


87.3


Resnet


90.8


التأسيس


90.2


Vgg16


89.2


Densenet121


90.6


Mobilenet


86.5



بشكل عام ، ليس كثيرًا ، ولكن مع مثل هذه العينة التدريبية الصغيرة ، لا يمكن للمرء أن يتوقع المزيد. لزيادة الدقة بشكل طفيف ، قمت بدمج مخرجات النماذج عن طريق حساب المتوسط:

 def create_meta_model(): model_names=[ "xception", "resnet", "inception", "vgg16", "densenet121", "mobilenet" ] model_input = Input(shape=(244,244,3)) submodels=[] i=0; for model_name in model_names: filename= "~/data/models/model_new_"+str(model_name)+".h5" submodel = keras.models.load_model(filename) submodel.name = model_name+"_"+str(i) i+=1 submodels.append(submodel(model_input)) out=average(submodels) model = Model(inputs = model_input,outputs=out) model.compile(optimizer=keras.optimizers.Adam(lr=1e-4), loss='binary_crossentropy', metrics=['accuracy']) return model 

كانت الدقة الناتجة 91.3 ٪. في هذه النتيجة ، قررت التوقف.

باستخدام المصنف


أخيرا المصنف جاهز ويمكن وضعه موضع التنفيذ! أقوم بإعداد بيانات الإدخال وأدير المصنف - أكثر من يوم بقليل وتم معالجة 1.7 مليون صورة. الآن الجزء الممتع هو النتائج. قم على الفور بإحضار أول عشر مدن في آخر عدد من الطرق مع تغطية جيدة:



الجدول الكامل (صورة قابلة للنقر)



وهنا هو تصنيف جودة الطريق من قبل الموضوعات الفيدرالية:



الجدول الكامل


التصنيف حسب المناطق الفيدرالية:



توزيع جودة الطرق في روسيا ككل:



حسنًا ، هذا كل شيء ، يمكن للجميع استخلاص النتائج بنفسه.

أخيرًا ، سأقدم أفضل الصور في كل فئة (والتي حصلت على الحد الأقصى للقيمة في فئتها):

الصورة



ملاحظة: في التعليقات ، أشار بحق إلى عدم وجود إحصاءات عن سنوات استلام الصور. أصحح وأعطي طاولة:

سنة


عدد الصور ، أجهزة الكمبيوتر


200837
200913
2010157030
201160724
201242387
201312148

2014141021

201546143

2016410385

2017324279

2018581961

Source: https://habr.com/ru/post/ar437542/


All Articles