Auto-update: 2025-10-23 15:04:00
This commit is contained in:
parent
7698240a79
commit
6170c48371
28 changed files with 19938 additions and 0 deletions
9
activite1/activite1.aux
Normal file
9
activite1/activite1.aux
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
\relax
|
||||||
|
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
||||||
|
\@nameuse{bbl@beforestart}
|
||||||
|
\catcode `:\active
|
||||||
|
\catcode `;\active
|
||||||
|
\catcode `!\active
|
||||||
|
\catcode `?\active
|
||||||
|
\babel@aux{french}{}
|
||||||
|
\gdef \@abspage@last{4}
|
||||||
750
activite1/activite1.log
Normal file
750
activite1/activite1.log
Normal file
|
|
@ -0,0 +1,750 @@
|
||||||
|
This is pdfTeX, Version 3.141592653-2.6-1.40.27 (TeX Live 2026/dev/Arch Linux) (preloaded format=pdflatex 2025.8.2) 23 OCT 2025 12:21
|
||||||
|
entering extended mode
|
||||||
|
restricted \write18 enabled.
|
||||||
|
%&-line parsing enabled.
|
||||||
|
**activite1.tex
|
||||||
|
(./activite1.tex
|
||||||
|
LaTeX2e <2024-11-01> patch level 2
|
||||||
|
L3 programming layer <2025-01-18>
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/article.cls
|
||||||
|
Document Class: article 2024/06/29 v1.4n Standard LaTeX document class
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/size11.clo
|
||||||
|
File: size11.clo 2024/06/29 v1.4n Standard LaTeX file (size option)
|
||||||
|
)
|
||||||
|
\c@part=\count196
|
||||||
|
\c@section=\count197
|
||||||
|
\c@subsection=\count198
|
||||||
|
\c@subsubsection=\count199
|
||||||
|
\c@paragraph=\count266
|
||||||
|
\c@subparagraph=\count267
|
||||||
|
\c@figure=\count268
|
||||||
|
\c@table=\count269
|
||||||
|
\abovecaptionskip=\skip49
|
||||||
|
\belowcaptionskip=\skip50
|
||||||
|
\bibindent=\dimen141
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/inputenc.sty
|
||||||
|
Package: inputenc 2024/02/08 v1.3d Input encoding file
|
||||||
|
\inpenc@prehook=\toks17
|
||||||
|
\inpenc@posthook=\toks18
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/fontenc.sty
|
||||||
|
Package: fontenc 2021/04/29 v2.0v Standard LaTeX package
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/babel.sty
|
||||||
|
Package: babel 2025/02/14 v25.4 The multilingual framework for pdfLaTeX, LuaLaT
|
||||||
|
eX and XeLaTeX
|
||||||
|
\babel@savecnt=\count270
|
||||||
|
\U@D=\dimen142
|
||||||
|
\l@unhyphenated=\language5
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/txtbabel.def)
|
||||||
|
\bbl@readstream=\read2
|
||||||
|
\bbl@dirlevel=\count271
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel-french/francais.ldf
|
||||||
|
Language: francais 2024-07-25 v3.6c French support from the babel system
|
||||||
|
|
||||||
|
|
||||||
|
Package francais.ldf Warning: Option `francais' for Babel is *deprecated*,
|
||||||
|
(francais.ldf) it might be removed sooner or later. Please
|
||||||
|
(francais.ldf) use `french' instead; reported on input line 31.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel-french/french.ldf
|
||||||
|
Language: french 2024-07-25 v3.6c French support from the babel system
|
||||||
|
Package babel Info: Hyphen rules for 'acadian' set to \l@french
|
||||||
|
(babel) (\language4). Reported on input line 91.
|
||||||
|
Package babel Info: Hyphen rules for 'canadien' set to \l@french
|
||||||
|
(babel) (\language4). Reported on input line 92.
|
||||||
|
\FB@stdchar=\count272
|
||||||
|
Package babel Info: Making : an active character on input line 421.
|
||||||
|
Package babel Info: Making ; an active character on input line 422.
|
||||||
|
Package babel Info: Making ! an active character on input line 423.
|
||||||
|
Package babel Info: Making ? an active character on input line 424.
|
||||||
|
\FBguill@level=\count273
|
||||||
|
\FBold@everypar=\toks19
|
||||||
|
\FB@Mht=\dimen143
|
||||||
|
\mc@charclass=\count274
|
||||||
|
\mc@charfam=\count275
|
||||||
|
\mc@charslot=\count276
|
||||||
|
\std@mcc=\count277
|
||||||
|
\dec@mcc=\count278
|
||||||
|
\FB@parskip=\dimen144
|
||||||
|
\listindentFB=\dimen145
|
||||||
|
\descindentFB=\dimen146
|
||||||
|
\labelindentFB=\dimen147
|
||||||
|
\labelwidthFB=\dimen148
|
||||||
|
\leftmarginFB=\dimen149
|
||||||
|
\parindentFFN=\dimen150
|
||||||
|
\FBfnindent=\dimen151
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/carlisle/scalefnt.sty)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/geometry/geometry.sty
|
||||||
|
Package: geometry 2020/01/02 v5.9 Page Geometry
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty
|
||||||
|
Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
|
||||||
|
\KV@toks@=\toks20
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/iftex/ifvtex.sty
|
||||||
|
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty
|
||||||
|
Package: iftex 2024/12/12 v1.0g TeX engine tests
|
||||||
|
))
|
||||||
|
\Gm@cnth=\count279
|
||||||
|
\Gm@cntv=\count280
|
||||||
|
\c@Gm@tempcnt=\count281
|
||||||
|
\Gm@bindingoffset=\dimen152
|
||||||
|
\Gm@wd@mp=\dimen153
|
||||||
|
\Gm@odd@mp=\dimen154
|
||||||
|
\Gm@even@mp=\dimen155
|
||||||
|
\Gm@layoutwidth=\dimen156
|
||||||
|
\Gm@layoutheight=\dimen157
|
||||||
|
\Gm@layouthoffset=\dimen158
|
||||||
|
\Gm@layoutvoffset=\dimen159
|
||||||
|
\Gm@dimlist=\toks21
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
|
||||||
|
\pgfutil@everybye=\toks22
|
||||||
|
\pgfutil@tempdima=\dimen160
|
||||||
|
\pgfutil@tempdimb=\dimen161
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
|
||||||
|
\pgfutil@abb=\box52
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/pgf.revision.tex)
|
||||||
|
Package: pgfrcs 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
Package: pgf 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty
|
||||||
|
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty
|
||||||
|
Package: graphics 2024/08/06 v1.4g Standard LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/trig.sty
|
||||||
|
Package: trig 2023/12/02 v1.11 sin cos tan (DPC)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||||
|
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
|
||||||
|
)
|
||||||
|
Package graphics Info: Driver file: pdftex.def on input line 106.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||||
|
File: pdftex.def 2024/04/13 v1.2c Graphics/color driver for pdftex
|
||||||
|
))
|
||||||
|
\Gin@req@height=\dimen162
|
||||||
|
\Gin@req@width=\dimen163
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
|
||||||
|
Package: pgfsys 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||||
|
\pgfkeys@pathtoks=\toks23
|
||||||
|
\pgfkeys@temptoks=\toks24
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfiltered.code.te
|
||||||
|
x
|
||||||
|
\pgfkeys@tmptoks=\toks25
|
||||||
|
))
|
||||||
|
\pgf@x=\dimen164
|
||||||
|
\pgf@y=\dimen165
|
||||||
|
\pgf@xa=\dimen166
|
||||||
|
\pgf@ya=\dimen167
|
||||||
|
\pgf@xb=\dimen168
|
||||||
|
\pgf@yb=\dimen169
|
||||||
|
\pgf@xc=\dimen170
|
||||||
|
\pgf@yc=\dimen171
|
||||||
|
\pgf@xd=\dimen172
|
||||||
|
\pgf@yd=\dimen173
|
||||||
|
\w@pgf@writea=\write3
|
||||||
|
\r@pgf@reada=\read3
|
||||||
|
\c@pgf@counta=\count282
|
||||||
|
\c@pgf@countb=\count283
|
||||||
|
\c@pgf@countc=\count284
|
||||||
|
\c@pgf@countd=\count285
|
||||||
|
\t@pgf@toka=\toks26
|
||||||
|
\t@pgf@tokb=\toks27
|
||||||
|
\t@pgf@tokc=\toks28
|
||||||
|
\pgf@sys@id@count=\count286
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg
|
||||||
|
File: pgf.cfg 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
Driver file for pgf: pgfsys-pdftex.def
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
|
||||||
|
File: pgfsys-pdftex.def 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def
|
||||||
|
File: pgfsys-common-pdf.def 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex
|
||||||
|
File: pgfsyssoftpath.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfsyssoftpath@smallbuffer@items=\count287
|
||||||
|
\pgfsyssoftpath@bigbuffer@items=\count288
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex
|
||||||
|
File: pgfsysprotocol.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/xcolor/xcolor.sty
|
||||||
|
Package: xcolor 2024/09/29 v3.02 LaTeX color extensions (UK)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-cfg/color.cfg
|
||||||
|
File: color.cfg 2016/01/02 v1.6 sample color configuration
|
||||||
|
)
|
||||||
|
Package xcolor Info: Driver file: pdftex.def on input line 274.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/mathcolor.ltx)
|
||||||
|
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1349.
|
||||||
|
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1353.
|
||||||
|
Package xcolor Info: Model `RGB' extended on input line 1365.
|
||||||
|
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1367.
|
||||||
|
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1368.
|
||||||
|
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1369.
|
||||||
|
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1370.
|
||||||
|
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1371.
|
||||||
|
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1372.
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
|
||||||
|
Package: pgfcore 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex
|
||||||
|
\pgfmath@dimen=\dimen174
|
||||||
|
\pgfmath@count=\count289
|
||||||
|
\pgfmath@box=\box53
|
||||||
|
\pgfmath@toks=\toks29
|
||||||
|
\pgfmath@stack@operand=\toks30
|
||||||
|
\pgfmath@stack@operation=\toks31
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code
|
||||||
|
.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.te
|
||||||
|
x) (/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics
|
||||||
|
.code.tex) (/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex
|
||||||
|
\c@pgfmathroundto@lastzeros=\count290
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfint.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex
|
||||||
|
File: pgfcorepoints.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@picminx=\dimen175
|
||||||
|
\pgf@picmaxx=\dimen176
|
||||||
|
\pgf@picminy=\dimen177
|
||||||
|
\pgf@picmaxy=\dimen178
|
||||||
|
\pgf@pathminx=\dimen179
|
||||||
|
\pgf@pathmaxx=\dimen180
|
||||||
|
\pgf@pathminy=\dimen181
|
||||||
|
\pgf@pathmaxy=\dimen182
|
||||||
|
\pgf@xx=\dimen183
|
||||||
|
\pgf@xy=\dimen184
|
||||||
|
\pgf@yx=\dimen185
|
||||||
|
\pgf@yy=\dimen186
|
||||||
|
\pgf@zx=\dimen187
|
||||||
|
\pgf@zy=\dimen188
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex
|
||||||
|
File: pgfcorepathconstruct.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@path@lastx=\dimen189
|
||||||
|
\pgf@path@lasty=\dimen190
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex
|
||||||
|
File: pgfcorepathusage.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@shorten@end@additional=\dimen191
|
||||||
|
\pgf@shorten@start@additional=\dimen192
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex
|
||||||
|
File: pgfcorescopes.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfpic=\box54
|
||||||
|
\pgf@hbox=\box55
|
||||||
|
\pgf@layerbox@main=\box56
|
||||||
|
\pgf@picture@serial@count=\count291
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex
|
||||||
|
File: pgfcoregraphicstate.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgflinewidth=\dimen193
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.t
|
||||||
|
ex
|
||||||
|
File: pgfcoretransformations.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@pt@x=\dimen194
|
||||||
|
\pgf@pt@y=\dimen195
|
||||||
|
\pgf@pt@temp=\dimen196
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
|
||||||
|
File: pgfcorequick.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex
|
||||||
|
File: pgfcoreobjects.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.te
|
||||||
|
x
|
||||||
|
File: pgfcorepathprocessing.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex
|
||||||
|
File: pgfcorearrows.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfarrowsep=\dimen197
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
|
||||||
|
File: pgfcoreshade.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@max=\dimen198
|
||||||
|
\pgf@sys@shading@range@num=\count292
|
||||||
|
\pgf@shadingcount=\count293
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
|
||||||
|
File: pgfcoreimage.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex
|
||||||
|
File: pgfcoreexternal.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfexternal@startupbox=\box57
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex
|
||||||
|
File: pgfcorelayers.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex
|
||||||
|
File: pgfcoretransparency.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex
|
||||||
|
File: pgfcorepatterns.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex
|
||||||
|
File: pgfcorerdf.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
|
||||||
|
File: pgfmoduleshapes.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfnodeparttextbox=\box58
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
|
||||||
|
File: pgfmoduleplot.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty
|
||||||
|
Package: pgfcomp-version-0-65 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@nodesepstart=\dimen199
|
||||||
|
\pgf@nodesepend=\dimen256
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty
|
||||||
|
Package: pgfcomp-version-1-18 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/math/pgfmath.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
|
||||||
|
Package: pgffor 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgffor@iter=\dimen257
|
||||||
|
\pgffor@skip=\dimen258
|
||||||
|
\pgffor@stack=\toks32
|
||||||
|
\pgffor@toks=\toks33
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
|
||||||
|
Package: tikz 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.te
|
||||||
|
x
|
||||||
|
File: pgflibraryplothandlers.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@plot@mark@count=\count294
|
||||||
|
\pgfplotmarksize=\dimen259
|
||||||
|
)
|
||||||
|
\tikz@lastx=\dimen260
|
||||||
|
\tikz@lasty=\dimen261
|
||||||
|
\tikz@lastxsaved=\dimen262
|
||||||
|
\tikz@lastysaved=\dimen263
|
||||||
|
\tikz@lastmovetox=\dimen264
|
||||||
|
\tikz@lastmovetoy=\dimen265
|
||||||
|
\tikzleveldistance=\dimen266
|
||||||
|
\tikzsiblingdistance=\dimen267
|
||||||
|
\tikz@figbox=\box59
|
||||||
|
\tikz@figbox@bg=\box60
|
||||||
|
\tikz@tempbox=\box61
|
||||||
|
\tikz@tempbox@bg=\box62
|
||||||
|
\tikztreelevel=\count295
|
||||||
|
\tikznumberofchildren=\count296
|
||||||
|
\tikznumberofcurrentchild=\count297
|
||||||
|
\tikz@fig@count=\count298
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
|
||||||
|
File: pgfmodulematrix.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfmatrixcurrentrow=\count299
|
||||||
|
\pgfmatrixcurrentcolumn=\count300
|
||||||
|
\pgf@matrix@numberofcolumns=\count301
|
||||||
|
)
|
||||||
|
\tikz@expandcount=\count302
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
topaths.code.tex
|
||||||
|
File: tikzlibrarytopaths.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))) (/usr/share/texmf-dist/tex/latex/amsmath/amsmath.sty
|
||||||
|
Package: amsmath 2024/11/05 v2.17t AMS math features
|
||||||
|
\@mathmargin=\skip51
|
||||||
|
|
||||||
|
For additional information on amsmath, use the `?' option.
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amstext.sty
|
||||||
|
Package: amstext 2021/08/26 v2.01 AMS text
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsgen.sty
|
||||||
|
File: amsgen.sty 1999/11/30 v2.0 generic functions
|
||||||
|
\@emptytoks=\toks34
|
||||||
|
\ex@=\dimen268
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsbsy.sty
|
||||||
|
Package: amsbsy 1999/11/29 v1.2d Bold Symbols
|
||||||
|
\pmbraise@=\dimen269
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsopn.sty
|
||||||
|
Package: amsopn 2022/04/08 v2.04 operator names
|
||||||
|
)
|
||||||
|
\inf@bad=\count303
|
||||||
|
LaTeX Info: Redefining \frac on input line 233.
|
||||||
|
\uproot@=\count304
|
||||||
|
\leftroot@=\count305
|
||||||
|
LaTeX Info: Redefining \overline on input line 398.
|
||||||
|
LaTeX Info: Redefining \colon on input line 409.
|
||||||
|
\classnum@=\count306
|
||||||
|
\DOTSCASE@=\count307
|
||||||
|
LaTeX Info: Redefining \ldots on input line 495.
|
||||||
|
LaTeX Info: Redefining \dots on input line 498.
|
||||||
|
LaTeX Info: Redefining \cdots on input line 619.
|
||||||
|
\Mathstrutbox@=\box63
|
||||||
|
\strutbox@=\box64
|
||||||
|
LaTeX Info: Redefining \big on input line 721.
|
||||||
|
LaTeX Info: Redefining \Big on input line 722.
|
||||||
|
LaTeX Info: Redefining \bigg on input line 723.
|
||||||
|
LaTeX Info: Redefining \Bigg on input line 724.
|
||||||
|
\big@size=\dimen270
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OML on input line 742.
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OMS on input line 743.
|
||||||
|
\macc@depth=\count308
|
||||||
|
LaTeX Info: Redefining \bmod on input line 904.
|
||||||
|
LaTeX Info: Redefining \pmod on input line 909.
|
||||||
|
LaTeX Info: Redefining \smash on input line 939.
|
||||||
|
LaTeX Info: Redefining \relbar on input line 969.
|
||||||
|
LaTeX Info: Redefining \Relbar on input line 970.
|
||||||
|
\c@MaxMatrixCols=\count309
|
||||||
|
\dotsspace@=\muskip17
|
||||||
|
\c@parentequation=\count310
|
||||||
|
\dspbrk@lvl=\count311
|
||||||
|
\tag@help=\toks35
|
||||||
|
\row@=\count312
|
||||||
|
\column@=\count313
|
||||||
|
\maxfields@=\count314
|
||||||
|
\andhelp@=\toks36
|
||||||
|
\eqnshift@=\dimen271
|
||||||
|
\alignsep@=\dimen272
|
||||||
|
\tagshift@=\dimen273
|
||||||
|
\tagwidth@=\dimen274
|
||||||
|
\totwidth@=\dimen275
|
||||||
|
\lineht@=\dimen276
|
||||||
|
\@envbody=\toks37
|
||||||
|
\multlinegap=\skip52
|
||||||
|
\multlinetaggap=\skip53
|
||||||
|
\mathdisplay@stack=\toks38
|
||||||
|
LaTeX Info: Redefining \[ on input line 2953.
|
||||||
|
LaTeX Info: Redefining \] on input line 2954.
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/amssymb.sty
|
||||||
|
Package: amssymb 2013/01/14 v3.01 AMS font symbols
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/amsfonts.sty
|
||||||
|
Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
|
||||||
|
\symAMSa=\mathgroup4
|
||||||
|
\symAMSb=\mathgroup5
|
||||||
|
LaTeX Font Info: Redeclaring math symbol \hbar on input line 98.
|
||||||
|
LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
|
||||||
|
(Font) U/euf/m/n --> U/euf/b/n on input line 106.
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/enumitem/enumitem.sty
|
||||||
|
Package: enumitem 2025/02/06 v3.11 Customized lists
|
||||||
|
\labelindent=\skip54
|
||||||
|
\enit@outerparindent=\dimen277
|
||||||
|
\enit@toks=\toks39
|
||||||
|
\enit@inbox=\box65
|
||||||
|
\enit@count@id=\count315
|
||||||
|
\enitdp@description=\count316
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty
|
||||||
|
Package: tcolorbox 2024/10/22 version 6.4.1 text color boxes
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tools/verbatim.sty
|
||||||
|
Package: verbatim 2024-01-22 v1.5x LaTeX2e package for verbatim enhancements
|
||||||
|
\every@verbatim=\toks40
|
||||||
|
\verbatim@line=\toks41
|
||||||
|
\verbatim@in@stream=\read4
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/environ/environ.sty
|
||||||
|
Package: environ 2014/05/04 v0.3 A new way to define environments
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/trimspaces/trimspaces.sty
|
||||||
|
Package: trimspaces 2009/09/17 v1.1 Trim spaces around a token list
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/etoolbox/etoolbox.sty
|
||||||
|
Package: etoolbox 2025/02/11 v2.5l e-TeX tools for LaTeX (JAW)
|
||||||
|
\etb@tempcnta=\count317
|
||||||
|
)
|
||||||
|
\tcb@titlebox=\box66
|
||||||
|
\tcb@upperbox=\box67
|
||||||
|
\tcb@lowerbox=\box68
|
||||||
|
\tcb@phantombox=\box69
|
||||||
|
\c@tcbbreakpart=\count318
|
||||||
|
\c@tcblayer=\count319
|
||||||
|
\c@tcolorbox@number=\count320
|
||||||
|
\l__tcobox_tmpa_box=\box70
|
||||||
|
\l__tcobox_tmpa_dim=\dimen278
|
||||||
|
\tcb@temp=\box71
|
||||||
|
\tcb@temp=\box72
|
||||||
|
\tcb@temp=\box73
|
||||||
|
\tcb@temp=\box74
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty
|
||||||
|
Package: fancyhdr 2025/02/07 v5.2 Extensive control of page headers and footers
|
||||||
|
|
||||||
|
\f@nch@headwidth=\skip55
|
||||||
|
\f@nch@offset@elh=\skip56
|
||||||
|
\f@nch@offset@erh=\skip57
|
||||||
|
\f@nch@offset@olh=\skip58
|
||||||
|
\f@nch@offset@orh=\skip59
|
||||||
|
\f@nch@offset@elf=\skip60
|
||||||
|
\f@nch@offset@erf=\skip61
|
||||||
|
\f@nch@offset@olf=\skip62
|
||||||
|
\f@nch@offset@orf=\skip63
|
||||||
|
\f@nch@height=\skip64
|
||||||
|
\f@nch@footalignment=\skip65
|
||||||
|
\f@nch@widthL=\skip66
|
||||||
|
\f@nch@widthC=\skip67
|
||||||
|
\f@nch@widthR=\skip68
|
||||||
|
\@temptokenb=\toks42
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tools/multicol.sty
|
||||||
|
Package: multicol 2024/09/14 v1.9i multicolumn formatting (FMi)
|
||||||
|
\c@tracingmulticols=\count321
|
||||||
|
\mult@box=\box75
|
||||||
|
\multicol@leftmargin=\dimen279
|
||||||
|
\c@unbalance=\count322
|
||||||
|
\c@collectmore=\count323
|
||||||
|
\doublecol@number=\count324
|
||||||
|
\multicoltolerance=\count325
|
||||||
|
\multicolpretolerance=\count326
|
||||||
|
\full@width=\dimen280
|
||||||
|
\page@free=\dimen281
|
||||||
|
\premulticols=\dimen282
|
||||||
|
\postmulticols=\dimen283
|
||||||
|
\multicolsep=\skip69
|
||||||
|
\multicolbaselineskip=\skip70
|
||||||
|
\partial@page=\box76
|
||||||
|
\last@line=\box77
|
||||||
|
\mc@boxedresult=\box78
|
||||||
|
\maxbalancingoverflow=\dimen284
|
||||||
|
\mult@rightbox=\box79
|
||||||
|
\mult@grightbox=\box80
|
||||||
|
\mult@firstbox=\box81
|
||||||
|
\mult@gfirstbox=\box82
|
||||||
|
\@tempa=\box83
|
||||||
|
\@tempa=\box84
|
||||||
|
\@tempa=\box85
|
||||||
|
\@tempa=\box86
|
||||||
|
\@tempa=\box87
|
||||||
|
\@tempa=\box88
|
||||||
|
\@tempa=\box89
|
||||||
|
\@tempa=\box90
|
||||||
|
\@tempa=\box91
|
||||||
|
\@tempa=\box92
|
||||||
|
\@tempa=\box93
|
||||||
|
\@tempa=\box94
|
||||||
|
\@tempa=\box95
|
||||||
|
\@tempa=\box96
|
||||||
|
\@tempa=\box97
|
||||||
|
\@tempa=\box98
|
||||||
|
\@tempa=\box99
|
||||||
|
\@tempa=\box100
|
||||||
|
\@tempa=\box101
|
||||||
|
\@tempa=\box102
|
||||||
|
\@tempa=\box103
|
||||||
|
\@tempa=\box104
|
||||||
|
\@tempa=\box105
|
||||||
|
\@tempa=\box106
|
||||||
|
\@tempa=\box107
|
||||||
|
\@tempa=\box108
|
||||||
|
\@tempa=\box109
|
||||||
|
\@tempa=\box110
|
||||||
|
\@tempa=\box111
|
||||||
|
\@tempa=\box112
|
||||||
|
\@tempa=\box113
|
||||||
|
\@tempa=\box114
|
||||||
|
\@tempa=\box115
|
||||||
|
\@tempa=\box116
|
||||||
|
\@tempa=\box117
|
||||||
|
\@tempa=\box118
|
||||||
|
\c@minrows=\count327
|
||||||
|
\c@columnbadness=\count328
|
||||||
|
\c@finalcolumnbadness=\count329
|
||||||
|
\last@try=\dimen285
|
||||||
|
\multicolovershoot=\dimen286
|
||||||
|
\multicolundershoot=\dimen287
|
||||||
|
\mult@nat@firstbox=\box119
|
||||||
|
\colbreak@box=\box120
|
||||||
|
\mc@col@check@num=\count330
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
shapes.geometric.code.tex
|
||||||
|
File: tikzlibraryshapes.geometric.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.geomet
|
||||||
|
ric.code.tex
|
||||||
|
File: pgflibraryshapes.geometric.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
calc.code.tex
|
||||||
|
File: tikzlibrarycalc.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
|
||||||
|
File: l3backend-pdftex.def 2024-05-08 L3 backend support: PDF output (pdfTeX)
|
||||||
|
\l__color_backend_stack_int=\count331
|
||||||
|
\l__pdf_internal_box=\box121
|
||||||
|
) (./activite1.aux
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/locale/fr/babel-french.tex
|
||||||
|
Package babel Info: Importing font and identification data for french
|
||||||
|
(babel) from babel-fr.ini. Reported on input line 11.
|
||||||
|
))
|
||||||
|
\openout1 = `activite1.aux'.
|
||||||
|
|
||||||
|
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 33.
|
||||||
|
LaTeX Font Info: ... okay on input line 33.
|
||||||
|
LaTeX Info: Redefining \degres on input line 33.
|
||||||
|
Package french.ldf Info: Setting StandardItemizeEnv=true for
|
||||||
|
(french.ldf) compatibility with enumitem package,
|
||||||
|
(french.ldf) reported on input line 33.
|
||||||
|
Package french.ldf Info: Setting StandardEnumerateEnv=true for
|
||||||
|
(french.ldf) compatibility with enumitem package,
|
||||||
|
(french.ldf) reported on input line 33.
|
||||||
|
LaTeX Info: Redefining \up on input line 33.
|
||||||
|
|
||||||
|
*geometry* driver: auto-detecting
|
||||||
|
*geometry* detected driver: pdftex
|
||||||
|
*geometry* verbose mode - [ preamble ] result:
|
||||||
|
* driver: pdftex
|
||||||
|
* paper: a4paper
|
||||||
|
* layout: <same size as paper>
|
||||||
|
* layoutoffset:(h,v)=(0.0pt,0.0pt)
|
||||||
|
* modes:
|
||||||
|
* h-part:(L,W,R)=(56.9055pt, 483.69687pt, 56.9055pt)
|
||||||
|
* v-part:(T,H,B)=(56.9055pt, 731.23584pt, 56.9055pt)
|
||||||
|
* \paperwidth=597.50787pt
|
||||||
|
* \paperheight=845.04684pt
|
||||||
|
* \textwidth=483.69687pt
|
||||||
|
* \textheight=731.23584pt
|
||||||
|
* \oddsidemargin=-15.36449pt
|
||||||
|
* \evensidemargin=-15.36449pt
|
||||||
|
* \topmargin=-52.36449pt
|
||||||
|
* \headheight=12.0pt
|
||||||
|
* \headsep=25.0pt
|
||||||
|
* \topskip=11.0pt
|
||||||
|
* \footskip=30.0pt
|
||||||
|
* \marginparwidth=50.0pt
|
||||||
|
* \marginparsep=10.0pt
|
||||||
|
* \columnsep=10.0pt
|
||||||
|
* \skip\footins=10.0pt plus 4.0pt minus 2.0pt
|
||||||
|
* \hoffset=0.0pt
|
||||||
|
* \voffset=0.0pt
|
||||||
|
* \mag=1000
|
||||||
|
* \@twocolumnfalse
|
||||||
|
* \@twosidefalse
|
||||||
|
* \@mparswitchfalse
|
||||||
|
* \@reversemarginfalse
|
||||||
|
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||||
|
[Loading MPS to PDF converter (version 2006.09.02).]
|
||||||
|
\scratchcounter=\count332
|
||||||
|
\scratchdimen=\dimen288
|
||||||
|
\scratchbox=\box122
|
||||||
|
\nofMPsegments=\count333
|
||||||
|
\nofMParguments=\count334
|
||||||
|
\everyMPshowfont=\toks43
|
||||||
|
\MPscratchCnt=\count335
|
||||||
|
\MPscratchDim=\dimen289
|
||||||
|
\MPnumerator=\count336
|
||||||
|
\makeMPintoPDFobject=\count337
|
||||||
|
\everyMPtoPDFconversion=\toks44
|
||||||
|
) (/usr/share/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
|
||||||
|
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
|
||||||
|
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
|
||||||
|
85.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||||
|
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
|
||||||
|
e
|
||||||
|
))
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msa on input line 59.
|
||||||
|
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||||
|
File: umsa.fd 2013/01/14 v3.01 AMS symbols A
|
||||||
|
)
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msb on input line 59.
|
||||||
|
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||||
|
File: umsb.fd 2013/01/14 v3.01 AMS symbols B
|
||||||
|
)
|
||||||
|
|
||||||
|
[1
|
||||||
|
|
||||||
|
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}{/usr/share/texmf-dist/fonts
|
||||||
|
/enc/dvips/cm-super/cm-super-t1.enc}]
|
||||||
|
|
||||||
|
[2]
|
||||||
|
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[4] (./activite1.aux)
|
||||||
|
***********
|
||||||
|
LaTeX2e <2024-11-01> patch level 2
|
||||||
|
L3 programming layer <2025-01-18>
|
||||||
|
***********
|
||||||
|
)
|
||||||
|
Here is how much of TeX's memory you used:
|
||||||
|
19631 strings out of 475142
|
||||||
|
396084 string characters out of 5765947
|
||||||
|
784639 words of memory out of 5000000
|
||||||
|
42341 multiletter control sequences out of 15000+600000
|
||||||
|
571118 words of font info for 64 fonts, out of 8000000 for 9000
|
||||||
|
14 hyphenation exceptions out of 8191
|
||||||
|
102i,11n,107p,410b,737s stack positions out of 10000i,1000n,20000p,200000b,200000s
|
||||||
|
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/
|
||||||
|
texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texmf-dist/font
|
||||||
|
s/type1/public/amsfonts/cm/cmsy10.pfb></usr/share/texmf-dist/fonts/type1/public
|
||||||
|
/amsfonts/symbols/msam10.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super
|
||||||
|
/sfbx1095.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfbx1200.pfb><
|
||||||
|
/usr/share/texmf-dist/fonts/type1/public/cm-super/sfbx1440.pfb></usr/share/texm
|
||||||
|
f-dist/fonts/type1/public/cm-super/sfbx2488.pfb></usr/share/texmf-dist/fonts/ty
|
||||||
|
pe1/public/cm-super/sfrm1000.pfb></usr/share/texmf-dist/fonts/type1/public/cm-s
|
||||||
|
uper/sfrm1095.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfti1095.p
|
||||||
|
fb>
|
||||||
|
Output written on activite1.pdf (4 pages, 182024 bytes).
|
||||||
|
PDF statistics:
|
||||||
|
76 PDF objects out of 1000 (max. 8388607)
|
||||||
|
47 compressed objects within 1 object stream
|
||||||
|
0 named destinations out of 1000 (max. 500000)
|
||||||
|
13 words of extra memory for PDF output out of 10000 (max. 10000000)
|
||||||
|
|
||||||
BIN
activite1/activite1.pdf
Normal file
BIN
activite1/activite1.pdf
Normal file
Binary file not shown.
BIN
activite1/activite1.synctex.gz
Normal file
BIN
activite1/activite1.synctex.gz
Normal file
Binary file not shown.
301
activite1/activite1.tex
Normal file
301
activite1/activite1.tex
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
\documentclass[a4paper,11pt]{article}
|
||||||
|
|
||||||
|
% Packages
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[francais]{babel}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{enumitem}
|
||||||
|
\usepackage{xcolor}
|
||||||
|
\usepackage{tcolorbox}
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\usepackage{multicol}
|
||||||
|
|
||||||
|
% Configuration de la page
|
||||||
|
\geometry{margin=2cm}
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[C]{Page \thepage/4 -- Activité k-NN}
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
|
||||||
|
% Couleurs personnalisées
|
||||||
|
\definecolor{classA}{RGB}{231,76,60}
|
||||||
|
\definecolor{classB}{RGB}{52,152,219}
|
||||||
|
\definecolor{lightblue}{RGB}{227,242,253}
|
||||||
|
\definecolor{lightyellow}{RGB}{255,243,205}
|
||||||
|
|
||||||
|
% Configuration TikZ
|
||||||
|
\usetikzlibrary{shapes.geometric,calc}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% ============= PAGE 1 =============
|
||||||
|
\begin{center}
|
||||||
|
{\Huge \textbf{Activité débranchée : k-NN}}\\[0.3cm]
|
||||||
|
{\Large \textbf{Les k Plus Proches Voisins}}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{Objectif :} Comprendre comment l'algorithme k-NN classifie un nouveau point en utilisant la proximité avec les points d'apprentissage.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightblue,colframe=blue!75!black,title=\textbf{Principe}]
|
||||||
|
\begin{itemize}[leftmargin=*]
|
||||||
|
\item On dispose d'un ensemble de points déjà classifiés (points d'apprentissage)
|
||||||
|
\item Pour classifier un nouveau point, on cherche ses \textit{k} plus proches voisins
|
||||||
|
\item La classe majoritaire parmi ces \textit{k} voisins devient la classe du nouveau point
|
||||||
|
\end{itemize}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\section*{Exercice 1 : Classification avec k = 3}
|
||||||
|
|
||||||
|
Voici un ensemble de points sur un plan. Les cercles rouges (\textcolor{classA}{$\bullet$}) sont de classe A, les carrés bleus (\textcolor{classB}{$\blacksquare$}) sont de classe B. Le point noir ($\star$) est à classifier.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=1.2]
|
||||||
|
% Grille
|
||||||
|
\draw[gray!30, step=1] (0,0) grid (8,8);
|
||||||
|
|
||||||
|
% Axes et cadre
|
||||||
|
\draw[thick] (0,0) rectangle (8,8);
|
||||||
|
|
||||||
|
% Points de classe A (cercles rouges)
|
||||||
|
\foreach \point in {(1,7), (1.5,6), (2,7.5), (2.5,6.5), (1.5,5), (2.5,5.5), (3,7)} {
|
||||||
|
\fill[classA] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Points de classe B (carrés bleus)
|
||||||
|
\fill[classB] (5,2) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]5,2) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (5.5,3) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]5.5,3) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (6,1.5) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]6,1.5) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (6.5,2.5) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]6.5,2.5) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (5.5,1) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]5.5,1) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (7,2) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]7,2) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
\fill[classB] (6.5,3.5) circle (0.15);
|
||||||
|
\fill[classB] ([shift={(-0.12,-0.12)}]6.5,3.5) rectangle ++(0.24,0.24);
|
||||||
|
|
||||||
|
% Point à classifier (étoile noire)
|
||||||
|
\node[star,star points=5,star point ratio=2.5,fill=black,draw=black,thick,minimum size=0.6cm] at (4,4.5) {};
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
% Légende
|
||||||
|
\begin{tabular}{ccccc}
|
||||||
|
\textcolor{classA}{$\bullet$} Classe A & \quad &
|
||||||
|
\textcolor{classB}{$\blacksquare$} Classe B & \quad &
|
||||||
|
$\star$ À classifier
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{Questions :}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Identifiez les 3 points les plus proches du point noir $\star$. Tracez les distances sur le graphique ci-dessus.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
Distances : \underline{\hspace{3cm}} \underline{\hspace{3cm}} \underline{\hspace{3cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Parmi ces 3 points, combien sont de classe A ? \underline{\hspace{1.5cm}} De classe B ? \underline{\hspace{1.5cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item À quelle classe appartient donc le point noir avec $k = 3$ ? \underline{\hspace{3cm}}
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
% ============= PAGE 2 =============
|
||||||
|
%\newpage
|
||||||
|
|
||||||
|
\section*{Exercice 2 : Influence du paramètre k}
|
||||||
|
|
||||||
|
Reprenez le même graphique que l'exercice 1.
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{a) Avec k = 1 (1 seul voisin)}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Quel est le point le plus proche ? \underline{\hspace{5cm}}
|
||||||
|
\item Classification du point noir : \underline{\hspace{5cm}}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{b) Avec k = 5 (5 voisins)}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Listez les 5 points les plus proches : \underline{\hspace{7cm}}
|
||||||
|
|
||||||
|
\vspace{0.2cm}
|
||||||
|
\underline{\hspace{10cm}}
|
||||||
|
|
||||||
|
\item Nombre de classe A : \underline{\hspace{2cm}} \quad Nombre de classe B : \underline{\hspace{2cm}}
|
||||||
|
\item Classification du point noir : \underline{\hspace{5cm}}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{c) Avec k = 7 (tous les voisins de chaque classe)}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Nombre de classe A : \underline{\hspace{2cm}} \quad Nombre de classe B : \underline{\hspace{2cm}}
|
||||||
|
\item Classification du point noir : \underline{\hspace{5cm}}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightyellow,colframe=orange!75!black,title=\textbf{Réflexion}]
|
||||||
|
|
||||||
|
\textbf{1. La classification change-t-elle selon la valeur de k ? Pourquoi ?}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{2. Que se passe-t-il si k est trop petit (k = 1) ?}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{3. Que se passe-t-il si k est trop grand (k = nombre total de points) ?}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
% ============= PAGE 3 =============
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section*{Exercice 3 : À vous de jouer !}
|
||||||
|
|
||||||
|
Créez votre propre situation de classification avec $k = 3$.
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=1.3]
|
||||||
|
% Grille fine
|
||||||
|
\draw[gray!20, step=1] (0,0) grid (12,12);
|
||||||
|
|
||||||
|
% Axes et cadre
|
||||||
|
\draw[very thick] (0,0) rectangle (12,12);
|
||||||
|
|
||||||
|
% Graduations
|
||||||
|
\foreach \x in {0,2,4,6,8,10,12} {
|
||||||
|
\node[below] at (\x,-0.2) {\small \x};
|
||||||
|
}
|
||||||
|
\foreach \y in {0,2,4,6,8,10,12} {
|
||||||
|
\node[left] at (-0.2,\y) {\small \y};
|
||||||
|
}
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightblue,colframe=blue!75!black,title=\textbf{Instructions}]
|
||||||
|
\begin{itemize}
|
||||||
|
\item Placez au moins 10 points : 5 cercles rouges (classe A) et 5 carrés bleus (classe B)
|
||||||
|
\item Placez une étoile noire (point à classifier)
|
||||||
|
\item Tracez les 3 distances les plus courtes
|
||||||
|
\item Déterminez la classe du point noir
|
||||||
|
\end{itemize}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{Classification finale :} \underline{\hspace{5cm}}
|
||||||
|
|
||||||
|
% ============= PAGE 4 =============
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section*{Pour aller plus loin}
|
||||||
|
|
||||||
|
\subsection*{Applications réelles de k-NN}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Reconnaissance d'écriture manuscrite
|
||||||
|
\item Systèmes de recommandation (films, musique, produits)
|
||||||
|
\item Diagnostic médical (classification de maladies)
|
||||||
|
\item Détection de spam dans les emails
|
||||||
|
\item Reconnaissance faciale
|
||||||
|
\item Prévision météorologique
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{Questions de réflexion}
|
||||||
|
|
||||||
|
\textbf{1. Avantages de k-NN :}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Simple à comprendre et à implémenter
|
||||||
|
\item Pas besoin d'entraînement complexe
|
||||||
|
\item Fonctionne bien pour des frontières non linéaires
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\textbf{2. Limitations de k-NN :}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Lent avec beaucoup de données (doit calculer toutes les distances)
|
||||||
|
\item Sensible aux données aberrantes
|
||||||
|
\item Nécessite de choisir la bonne valeur de $k$
|
||||||
|
\item Ne fonctionne pas bien si les classes sont déséquilibrées
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\textbf{3. Comment choisir k ?}
|
||||||
|
\begin{itemize}
|
||||||
|
\item $k$ trop petit ($k=1$) : sensible au bruit, risque de sur-apprentissage
|
||||||
|
\item $k$ trop grand : perd les détails, risque de sous-apprentissage
|
||||||
|
\item Conseil : tester plusieurs valeurs et choisir celle qui donne les meilleurs résultats
|
||||||
|
\item Souvent, $k$ impair pour éviter les égalités ($k = 3, 5, 7...$)
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightyellow,colframe=orange!75!black,title=\textbf{Défi bonus}]
|
||||||
|
Imaginez une situation où k-NN pourrait donner un mauvais résultat. Dessinez cette situation sur une feuille séparée et expliquez pourquoi.
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
\textit{Indices : Pensez aux données bruitées, aux classes déséquilibrées, ou aux points isolés...}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
388
activite1/communes-de-corse-en-corse-et-francais.csv
Normal file
388
activite1/communes-de-corse-en-corse-et-francais.csv
Normal file
File diff suppressed because one or more lines are too long
693
activite1/generate_interactive_map.py
Normal file
693
activite1/generate_interactive_map.py
Normal file
|
|
@ -0,0 +1,693 @@
|
||||||
|
"""
|
||||||
|
Script pour générer une page HTML interactive avec les données des villages corses embarquées.
|
||||||
|
Usage: python generate_interactive_map.py villages_corse.csv
|
||||||
|
"""
|
||||||
|
|
||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def parse_coordinates(point_geo_str):
|
||||||
|
"""Parse la colonne Point_Geo"""
|
||||||
|
try:
|
||||||
|
parts = point_geo_str.split(',')
|
||||||
|
lat = float(parts[0].strip())
|
||||||
|
lon = float(parts[1].strip())
|
||||||
|
return lat, lon
|
||||||
|
except:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def load_villages_from_csv(csv_file):
|
||||||
|
"""Charge les villages depuis le CSV"""
|
||||||
|
villages = []
|
||||||
|
|
||||||
|
with open(csv_file, 'r', encoding='utf-8') as f:
|
||||||
|
reader = csv.reader(f, delimiter=';')
|
||||||
|
next(reader) # Skip header
|
||||||
|
|
||||||
|
for row in reader:
|
||||||
|
if len(row) >= 18:
|
||||||
|
lat, lon = parse_coordinates(row[17])
|
||||||
|
if lat and lon:
|
||||||
|
villages.append({
|
||||||
|
'name': row[0],
|
||||||
|
'nameCorse': row[1],
|
||||||
|
'lat': lat,
|
||||||
|
'lon': lon,
|
||||||
|
'dept': row[9],
|
||||||
|
'altitude': float(row[15]) if row[15] else 0
|
||||||
|
})
|
||||||
|
|
||||||
|
return villages
|
||||||
|
|
||||||
|
def generate_html(villages, output_file='knn_interactive_full.html'):
|
||||||
|
"""Génère le fichier HTML avec les données embarquées"""
|
||||||
|
|
||||||
|
villages_json = json.dumps(villages, ensure_ascii=False)
|
||||||
|
|
||||||
|
html_content = f'''<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Classification k-NN Interactive - Corse</title>
|
||||||
|
|
||||||
|
<!-- Leaflet CSS -->
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}}
|
||||||
|
|
||||||
|
body {{
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.container {{
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.header {{
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.header h1 {{
|
||||||
|
font-size: 2.5em;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.header p {{
|
||||||
|
font-size: 1.2em;
|
||||||
|
opacity: 0.9;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.main-content {{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 350px 1fr;
|
||||||
|
gap: 0;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.sidebar {{
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 30px;
|
||||||
|
border-right: 2px solid #ddd;
|
||||||
|
max-height: 900px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.controls {{
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.controls h3 {{
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.control-group {{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.control-group label {{
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #555;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.slider-container {{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
input[type="range"] {{
|
||||||
|
flex: 1;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #ddd;
|
||||||
|
outline: none;
|
||||||
|
}}
|
||||||
|
|
||||||
|
input[type="range"]::-webkit-slider-thumb {{
|
||||||
|
appearance: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #667eea;
|
||||||
|
cursor: pointer;
|
||||||
|
}}
|
||||||
|
|
||||||
|
input[type="range"]::-moz-range-thumb {{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #667eea;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.k-value {{
|
||||||
|
background: #667eea;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
min-width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.result-box {{
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.result-box h3 {{
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #333;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.prediction {{
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.prediction.corse-sud {{
|
||||||
|
background: #ffebee;
|
||||||
|
color: #c62828;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.prediction.haute-corse {{
|
||||||
|
background: #e3f2fd;
|
||||||
|
color: #1565c0;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.prediction.no-result {{
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.coords {{
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.votes {{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.vote-item {{
|
||||||
|
text-align: center;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.vote-count {{
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.vote-count.red {{
|
||||||
|
color: #c62828;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.vote-count.blue {{
|
||||||
|
color: #1565c0;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbors-list {{
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-item {{
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-left: 4px solid #ddd;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-item.dept-2a {{
|
||||||
|
border-left-color: #c62828;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-item.dept-2b {{
|
||||||
|
border-left-color: #1565c0;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-name {{
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-corse {{
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.neighbor-distance {{
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.instructions {{
|
||||||
|
background: #fff3cd;
|
||||||
|
border-left: 4px solid #ffc107;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.instructions h4 {{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #856404;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.instructions ul {{
|
||||||
|
margin-left: 20px;
|
||||||
|
color: #856404;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.instructions li {{
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend {{
|
||||||
|
background: white;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend h4 {{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend-item {{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend-circle {{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #333;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend-circle.red {{
|
||||||
|
background: #e74c3c;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend-circle.blue {{
|
||||||
|
background: #3498db;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.legend-circle.marker {{
|
||||||
|
background: #95a5a6;
|
||||||
|
border: 3px solid #000;
|
||||||
|
}}
|
||||||
|
|
||||||
|
#map {{
|
||||||
|
height: 900px;
|
||||||
|
cursor: crosshair;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.leaflet-popup-content {{
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
}}
|
||||||
|
|
||||||
|
button {{
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
button:hover {{
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.btn-reset {{
|
||||||
|
background: #f44336;
|
||||||
|
color: white;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.btn-random {{
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.stats {{
|
||||||
|
background: #e3f2fd;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
color: #1565c0;
|
||||||
|
}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>🗺️ Classification k-NN Interactive</h1>
|
||||||
|
<p>Haute-Corse ou Corse du Sud ?</p>
|
||||||
|
<div class="stats">
|
||||||
|
<strong>{len(villages)}</strong> villages chargés
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="main-content">
|
||||||
|
<div class="sidebar">
|
||||||
|
<div class="instructions">
|
||||||
|
<h4>📋 Instructions</h4>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Cliquez</strong> n'importe où sur la carte</li>
|
||||||
|
<li>Ajustez la valeur de <strong>k</strong> avec le curseur</li>
|
||||||
|
<li>Observez les <strong>k plus proches villages</strong></li>
|
||||||
|
<li>La <strong>classification</strong> se fait par vote majoritaire</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<h3>⚙️ Paramètres</h3>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>Nombre de voisins (k) :</label>
|
||||||
|
<div class="slider-container">
|
||||||
|
<input type="range" id="kSlider" min="1" max="21" value="5" step="2">
|
||||||
|
<span class="k-value" id="kValue">5</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn-random" onclick="placeRandomPoint()">🎲 Point Aléatoire</button>
|
||||||
|
<button class="btn-reset" onclick="resetClassification()">🔄 Réinitialiser</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="result-box" id="resultBox">
|
||||||
|
<h3>🎯 Résultat</h3>
|
||||||
|
<div class="prediction no-result" id="prediction">
|
||||||
|
Cliquez sur la carte
|
||||||
|
</div>
|
||||||
|
<div class="coords" id="coords"></div>
|
||||||
|
<div id="votesContainer" style="display: none;">
|
||||||
|
<div class="votes">
|
||||||
|
<div class="vote-item">
|
||||||
|
<div class="vote-count red" id="votes2A">0</div>
|
||||||
|
<div>Corse du Sud</div>
|
||||||
|
</div>
|
||||||
|
<div class="vote-item">
|
||||||
|
<div class="vote-count blue" id="votes2B">0</div>
|
||||||
|
<div>Haute-Corse</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4>🏘️ Plus proches voisins :</h4>
|
||||||
|
<div class="neighbors-list" id="neighborsList"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
<h4>Légende</h4>
|
||||||
|
<div class="legend-item">
|
||||||
|
<div class="legend-circle red"></div>
|
||||||
|
<span>Corse du Sud (2A)</span>
|
||||||
|
</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<div class="legend-circle blue"></div>
|
||||||
|
<span>Haute-Corse (2B)</span>
|
||||||
|
</div>
|
||||||
|
<div class="legend-item">
|
||||||
|
<div class="legend-circle marker"></div>
|
||||||
|
<span>Point à classifier</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Leaflet JS -->
|
||||||
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Données des villages (embarquées depuis le CSV)
|
||||||
|
const villages = {villages_json};
|
||||||
|
|
||||||
|
let map, testMarker, neighborMarkers = [], neighborLines = [];
|
||||||
|
let currentK = 5;
|
||||||
|
|
||||||
|
// Initialiser la carte
|
||||||
|
function initMap() {{
|
||||||
|
map = L.map('map').setView([42.15, 9.05], 9);
|
||||||
|
|
||||||
|
L.tileLayer('https://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', {{
|
||||||
|
attribution: '© OpenStreetMap contributors'
|
||||||
|
}}).addTo(map);
|
||||||
|
|
||||||
|
// Ajouter tous les villages
|
||||||
|
villages.forEach(village => {{
|
||||||
|
const color = village.dept === '2A' ? '#e74c3c' : '#3498db';
|
||||||
|
L.circleMarker([village.lat, village.lon], {{
|
||||||
|
radius: 3,
|
||||||
|
fillColor: color,
|
||||||
|
color: '#333',
|
||||||
|
weight: 1,
|
||||||
|
opacity: 1,
|
||||||
|
fillOpacity: 0.5
|
||||||
|
}}).bindPopup(`<b>${{village.name}}</b><br>${{village.nameCorse}}<br>${{village.dept}}`)
|
||||||
|
.addTo(map);
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Ajouter le gestionnaire de clic
|
||||||
|
map.on('click', onMapClick);
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Calcul de distance Haversine
|
||||||
|
function haversineDistance(lat1, lon1, lat2, lon2) {{
|
||||||
|
const R = 6371; // Rayon de la Terre en km
|
||||||
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
||||||
|
const dLon = (lon2 - lon1) * Math.PI / 180;
|
||||||
|
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
||||||
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
||||||
|
Math.sin(dLon/2) * Math.sin(dLon/2);
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||||
|
return R * c;
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Classification k-NN
|
||||||
|
function knnClassify(lat, lon, k) {{
|
||||||
|
// Calculer distances
|
||||||
|
const distances = villages.map(village => ({{
|
||||||
|
...village,
|
||||||
|
distance: haversineDistance(lat, lon, village.lat, village.lon)
|
||||||
|
}}));
|
||||||
|
|
||||||
|
// Trier par distance
|
||||||
|
distances.sort((a, b) => a.distance - b.distance);
|
||||||
|
|
||||||
|
// Prendre les k plus proches
|
||||||
|
const neighbors = distances.slice(0, k);
|
||||||
|
|
||||||
|
// Voter
|
||||||
|
const votes = {{ '2A': 0, '2B': 0 }};
|
||||||
|
neighbors.forEach(n => votes[n.dept]++);
|
||||||
|
|
||||||
|
const prediction = votes['2A'] > votes['2B'] ? '2A' : '2B';
|
||||||
|
|
||||||
|
return {{ prediction, neighbors, votes }};
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Gestionnaire de clic sur la carte
|
||||||
|
function onMapClick(e) {{
|
||||||
|
const lat = e.latlng.lat;
|
||||||
|
const lon = e.latlng.lng;
|
||||||
|
|
||||||
|
classifyPoint(lat, lon);
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Classifier un point
|
||||||
|
function classifyPoint(lat, lon) {{
|
||||||
|
// Supprimer les anciens marqueurs
|
||||||
|
if (testMarker) map.removeLayer(testMarker);
|
||||||
|
neighborMarkers.forEach(m => map.removeLayer(m));
|
||||||
|
neighborLines.forEach(l => map.removeLayer(l));
|
||||||
|
neighborMarkers = [];
|
||||||
|
neighborLines = [];
|
||||||
|
|
||||||
|
// Classifier
|
||||||
|
const result = knnClassify(lat, lon, currentK);
|
||||||
|
|
||||||
|
// Ajouter le marqueur du point test
|
||||||
|
testMarker = L.circleMarker([lat, lon], {{
|
||||||
|
radius: 12,
|
||||||
|
fillColor: '#95a5a6',
|
||||||
|
color: '#000',
|
||||||
|
weight: 3,
|
||||||
|
opacity: 1,
|
||||||
|
fillOpacity: 0.8
|
||||||
|
}}).addTo(map);
|
||||||
|
|
||||||
|
// Ajouter les marqueurs et lignes des voisins
|
||||||
|
result.neighbors.forEach(neighbor => {{
|
||||||
|
const nColor = neighbor.dept === '2A' ? '#e74c3c' : '#3498db';
|
||||||
|
|
||||||
|
// Ligne
|
||||||
|
const line = L.polyline(
|
||||||
|
[[lat, lon], [neighbor.lat, neighbor.lon]],
|
||||||
|
{{color: nColor, weight: 2, opacity: 0.5}}
|
||||||
|
).addTo(map);
|
||||||
|
neighborLines.push(line);
|
||||||
|
|
||||||
|
// Marqueur
|
||||||
|
const marker = L.circleMarker([neighbor.lat, neighbor.lon], {{
|
||||||
|
radius: 8,
|
||||||
|
fillColor: nColor,
|
||||||
|
color: '#333',
|
||||||
|
weight: 2,
|
||||||
|
opacity: 1,
|
||||||
|
fillOpacity: 0.8
|
||||||
|
}}).bindPopup(`<b>${{neighbor.name}}</b><br>${{neighbor.nameCorse}}<br>${{neighbor.dept}}<br>Distance: ${{neighbor.distance.toFixed(2)}} km`)
|
||||||
|
.addTo(map);
|
||||||
|
neighborMarkers.push(marker);
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Afficher les résultats
|
||||||
|
displayResults(lat, lon, result);
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Afficher les résultats
|
||||||
|
function displayResults(lat, lon, result) {{
|
||||||
|
const predictionDiv = document.getElementById('prediction');
|
||||||
|
const coordsDiv = document.getElementById('coords');
|
||||||
|
const votesContainer = document.getElementById('votesContainer');
|
||||||
|
const votes2A = document.getElementById('votes2A');
|
||||||
|
const votes2B = document.getElementById('votes2B');
|
||||||
|
const neighborsList = document.getElementById('neighborsList');
|
||||||
|
|
||||||
|
// Coordonnées
|
||||||
|
coordsDiv.textContent = `(${{lat.toFixed(4)}}, ${{lon.toFixed(4)}})`;
|
||||||
|
|
||||||
|
// Prédiction
|
||||||
|
const deptName = result.prediction === '2A' ? 'Corse du Sud (2A)' : 'Haute-Corse (2B)';
|
||||||
|
const cssClass = result.prediction === '2A' ? 'corse-sud' : 'haute-corse';
|
||||||
|
predictionDiv.textContent = deptName;
|
||||||
|
predictionDiv.className = 'prediction ' + cssClass;
|
||||||
|
|
||||||
|
// Votes
|
||||||
|
votes2A.textContent = result.votes['2A'];
|
||||||
|
votes2B.textContent = result.votes['2B'];
|
||||||
|
votesContainer.style.display = 'block';
|
||||||
|
|
||||||
|
// Liste des voisins
|
||||||
|
neighborsList.innerHTML = '';
|
||||||
|
result.neighbors.forEach(neighbor => {{
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.className = `neighbor-item dept-${{neighbor.dept.toLowerCase()}}`;
|
||||||
|
div.innerHTML = `
|
||||||
|
<div class="neighbor-name">${{neighbor.name}} (${{neighbor.dept}})</div>
|
||||||
|
<div class="neighbor-corse">${{neighbor.nameCorse}}</div>
|
||||||
|
<div class="neighbor-distance">Distance: ${{neighbor.distance.toFixed(2)}} km</div>
|
||||||
|
`;
|
||||||
|
neighborsList.appendChild(div);
|
||||||
|
}});
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Point aléatoire
|
||||||
|
function placeRandomPoint() {{
|
||||||
|
const lat = 41.3 + Math.random() * (43.0 - 41.3);
|
||||||
|
const lon = 8.5 + Math.random() * (9.6 - 8.5);
|
||||||
|
classifyPoint(lat, lon);
|
||||||
|
map.setView([lat, lon], 10);
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Réinitialiser
|
||||||
|
function resetClassification() {{
|
||||||
|
if (testMarker) map.removeLayer(testMarker);
|
||||||
|
neighborMarkers.forEach(m => map.removeLayer(m));
|
||||||
|
neighborLines.forEach(l => map.removeLayer(l));
|
||||||
|
neighborMarkers = [];
|
||||||
|
neighborLines = [];
|
||||||
|
testMarker = null;
|
||||||
|
|
||||||
|
document.getElementById('prediction').textContent = 'Cliquez sur la carte';
|
||||||
|
document.getElementById('prediction').className = 'prediction no-result';
|
||||||
|
document.getElementById('coords').textContent = '';
|
||||||
|
document.getElementById('votesContainer').style.display = 'none';
|
||||||
|
|
||||||
|
map.setView([42.15, 9.05], 9);
|
||||||
|
}}
|
||||||
|
|
||||||
|
// Gestionnaire du slider k
|
||||||
|
document.getElementById('kSlider').addEventListener('input', function(e) {{
|
||||||
|
currentK = parseInt(e.target.value);
|
||||||
|
document.getElementById('kValue').textContent = currentK;
|
||||||
|
|
||||||
|
// Reclassifier si un point existe
|
||||||
|
if (testMarker) {{
|
||||||
|
const latlng = testMarker.getLatLng();
|
||||||
|
classifyPoint(latlng.lat, latlng.lng);
|
||||||
|
}}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Initialisation
|
||||||
|
initMap();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>'''
|
||||||
|
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(html_content)
|
||||||
|
|
||||||
|
print(f"✅ Fichier HTML généré : {output_file}")
|
||||||
|
print(f"📊 {len(villages)} villages inclus")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python generate_interactive_map.py villages_corse.csv")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
csv_file = sys.argv[1]
|
||||||
|
villages = load_villages_from_csv(csv_file)
|
||||||
|
generate_html(villages)
|
||||||
137
activite1/knn_activite_debranchee.pdf
Normal file
137
activite1/knn_activite_debranchee.pdf
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
%PDF-1.4
|
||||||
|
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/F1 2 0 R /F2 3 0 R /F3 4 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /ZapfDingbats /Name /F3 /Subtype /Type1 /Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 12 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 13 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 14 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 15 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/PageMode /UseNone /Pages 11 0 R /Type /Catalog
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
/Author (anonymous) /CreationDate (D:20251023100834+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20251023100834+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
|
||||||
|
/Subject (unspecified) /Title (untitled) /Trapped /False
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
11 0 obj
|
||||||
|
<<
|
||||||
|
/Count 4 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R ] /Type /Pages
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
12 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2409
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Gat%$CQI5[(&dQ-EPH@r8@a,3>+d9%qe-??]@1rM:BM;gX<^DSfp1pgU;+EtPXs3qfM45Ya)c3FmZX!('ZBMdib,SDHM^7jr?=d'HMg#p1JNr!ki]ud`$ItrE*8iC-8:b=8lgP62b[2ZU;nk!qOookce[PO)+!TXq0o:>k#;'+deECq&&8,?RN=]Bj0s^TTqcYOr%0d,1*\7be\#ZfqEb^^j%']uY5*`8s1.I8Xrl!CiL5ShMTK)hdPJekjMZ!*5I^.B!t>0K\(qR3^E-QnG2$lg+)(7?^%o/W]#1F_)]bYb;ibG_TkioF;nkCX\+PmW]<4Ag>'$ZC#c9+&U=QcNj.Y4L@i^f`ZlaJ+GM>-DolJm7#&ZoaOk/F>qdA'M)oqebbO-da'f,*g%#SqZ3<q:AU-0#Sf/MM,BmZ9'ETXAlm]>MD]20_Sod$'&hg/IMj*iqq0GH6Uqm"tkhr([r3tU3Dr1l0qi=!^t:Tn)Jn`f^01ULWFC:fl'YWE=fEe]M=]V/V,.%UJ>BoF@G%jeWU9Bu>LP.K-n/^q_N7IRj7db<-XrZ!DamSH.FHJ!Dj6o?bVipkg3;nD-,lf5)SMRu<rH8a"(W+T$H-CpQVnal3gZ"mMKTVCUo2"dPpqm!B>clYimY]Jgd(Us*tEJA2(V@(<YCcZl&hr?H2J%qt07Uc0PYUL:YYWI;M6e\=7ms\+]C0tgipsba6:TnKf+`L73#O[@+GP6QlJk8o:BPPoLeAEuj*)&M%2kg7T'A`r>-AR`%DRdjaQ`H)4GbC6pd159pk0^0Cs*5pS5HCC&H-rs_,K25J=u_Zn7d%oIW4[V]R$URCNL^"Q'/PbCTKt&Gr'Ies0V]noK[R4.=/f6FD.Q?IXj!QjAnVe\'6?dG'AA+FV+%HZ$9Pek:!cRlh8c(1-aX2l8m;TK!a.gYTUE7Z9M6U+BG5QK<f;hQkt5_I1l:@"'XSai8uj!(:7&%<16WUr]<M6e1gsHWSRk]>;mI``VY,!H/SPlANRi'nN5Z(,ct4\^MPY.,Qf6ssL8%lYiL!Wj(Bc$rTaZJgk]KYb_!/]&X.h9]dU8Vr29ln6]OF4d9OF/&ACcNY$RV8UhGV2.R1cAr2ZZ3K[OK=/ZSTk:F3X";\%uj&(AVeJ@19EtUE`a>i^btfj6:LtdP57Ya"d]H,eCYH^6F5Kgmp-1A6'MtAPAen,U/G?S7%WTVU1ZkYV'(DV6]':khN`0Zo5#V)Ok&XjtrF@l\nD'g]omBnV*ad,V#pZU1b;KJJkIS5'.sDk.,%Hb",DHQ=\8qm!Mc'+qetG>-oRYbHaj#<;%UM?$M^k`bZo>8<U,P-Xj2p92%YhI)b2W;@#J+1olT<!^:MGK"qkkO:Wd4.D`)_,uFkYD.-Sa]OtIge4:qWo+k]_,p]Qb7V/Q8G@nGUm_$J:'3c$c;&>&X;G0J7+`1(q1JlYHQ:ZeBcm3.&<E;&a@UoaDk/!!iA%<sm1JlYGP0#m5Q8>Ek;N*Dh@i(`4fP1NnO^5h<Yq](_7F2]Gk'3"\l!'N11@$HSCatB*U%r7Hj-Zm+.eG$_9QHHAQ=m'&s,uCP(*V$Ph0Zt9cZKl`V^pJA5,X>$D4t9U>tA+N+iTbf^k+,^HbiV3?'sco]Vs#u4.DI&ZI+Nj_R8V!1f<6PS%df#$\pgDc#K8k#Zr(#EKB442Z:Vu(?.aqrPq0TP_Y6Sp2rs&e%mt@W4b0s?Bkp"n.8E0^m83t("u[OOk*j*`*j:GmQ6YtCQ@GjaD5DMWKj(qs3#)P2<'YEMW:!3(cYO*<Zt*T@)u8+O9;AU[h0"O%LB\d9O`!uNYpmmM45>G:_k6A8VQ0QL>%aM5tmPQ&e<h<X%G:,_DCB_V,iG1d1VX>@GRhX)=rieMUO]6%iKZLku[ATdcd4E1pnni_\@2+][B\W)MjCI97fqdAg&DDWX@<l34_ZNfV;H_Zll\=XBRBpN&MId9N0@IFVB:*MbUP%@WnKVE%^UGk^ILn'7B3lJ^#AbnNQ[,I#0qslca\agOFO?8J^*]ZSQ`<qnJrpmD[UjhU:X$jlb;Nbj45^)gP+0,YT0"<E&a)fWP=ni@K()'kag@CYcoETlE2X`),UP"D&<WH9D@b&f'V8V3GVXo_O4L'e1b<rJ=Do<nc!3<0esE;Y-!Fl80&JMO/P3(LA'K^B$lb4qWr"#lf(d't2lij8$%/=$A#8pU'(HFb8"JfAQl=[f&-KJ#W(3&Dt@Ia-u\+]QsNapMNH]6f#s)f%kSLqkbD&]rBt`?t_IdcC5aK)WR)@d30_1.Ikm]oWRg-h>Hl)0fUpc.72iF7Q=XWoTUfHkTN/^V7=5Gc^aI9[_I&nTg)6Ud8.r48&F[3B@/&<[C=(.=5bEmhQ.Ed=I]=S[[U"B=RZ"WE/7;%lWkT=7*DAZDct2dF6dN45:6%N)?~>endstream
|
||||||
|
endobj
|
||||||
|
13 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 845
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
GauHJD+iYL&H;+$QuCMAVjVs?TnjHl"Y$S7j$ANA:K)>VR2;"bqG&q]c^/D5J[`[Rc#/n]k':QNQQY6/`Flmb3(i/i(BP52c@HZZ85J/'h21G!8B,e3B"^qi'AB,L_@p%LOhC4G/n"GK2Df]A#8"*M?`SJ*LPk!7HWXlS[[9XWFA7:d4\1&gqYi,`qiF2snIgusW6*eMF;gH>W5<I$!t9@l,/?X2/ME%J5/?Y@hh=.1#Tj/+<rn1(@V)l/34oPX>eqfETC!8uTeGB%0&!%gmJTg;2F1sa.@ph;?;O&bd>&?$gC;O]l_5:FA`(A1WUn:5#Oq?TG_l47^2XW'\P\^>A_+</]Z@F^W2lje7&fIG@ATPOqF[?<8PiQ`,1P:oZ8@cA=$3l0&nR:qAX&&&:PuT=U:4r#`mD_lHX*rh!d\HPOXE83A27VCWu#E=[-%J\J]7\FG6l"EamRR4mM#jA(6P@D#c+"WCMBl?r4YF^"mYB%,]TYZN9)f6C1n#i6fGEBBT7+P8YXcS[85")80j%K9u_cGjd&:*1>E@)q\uq!jWt8m`Z-4VPACYV*<;!o?%`aELJW"QBLBmWAHk(r)>[qfl\bSVpUY:Gqmq<1IoEbpF6b<(kqchsP0qZ/Q=dFe2Cl0mSlY("W8L=@.=i[?G&(u8#>iRR.CWu\7CNC$2f][k:HM<\(9T'Z/QemD[<G?YKOsA)Nb^8=,[?.hU*UGcZkHb::WT)[[RH4`%[GCMat:M4#NOpsgsUSGP+9[6W=gIn`se<`Rdme[3aZT%NK's=];uu%E'/_Y+f#ef<C0Vu0)68pPhoT4bCn5&5F(BJGpFj;>IXhuIfKgqcK"~>endstream
|
||||||
|
endobj
|
||||||
|
14 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 832
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
GasbY95i9E'Lqim'pi4Li\Ksm,o.1%6=PM]b=K^a;rj+oOWT,Koit;jRT=;tUt@\rSF=a^kCs)62ijTM&`>^&=78.g!SJK4KaP+]E0KZ5(VjVC)U6.pW6ba.(S68%)S%dJZ6NW0r!?(p(',[c_-Sl$^ZrOegAptj*u]BD$/%IP0BWlRB/)e:'k%5[mVRo-g[(d!i@gV2-GZU[:NU<oY0X_cY(j%;OLK(P<u,G3rsAr-K\%>d(!g@3QOc.f^N\3@-4S5OGR78&jP&n\L2t#rcj?a0LPJqdTo:I)&15)tMs@f+b;B173&m"8*U=Fq8tiN<)g%OJKq68)/l=[sf%ug3H'JphN=]mobXSeqBVgfIG@I%Jc-S54e2t"aCDennP'*/FVUp-)RauQIS_30!%[GBbnP3oDX-lDq\64/kFri/e6#1aDn'!]';PR5Ed>hnIC-!Hln\dJn9rjtYpIZgeM2bgh;&NpXn&.,t?D(3?-f0]Na%FY)nYFqHD-;jkI<S_oXYUouo3kg:-ar8>*k@M,[5/c8`hB8nQ$=[bl*[neNlf4$Z!m"Ks.4.';@2u%nCX0n<c-I\`R&^1\9crqI+0lm:C2_En!&dJ4gu1j+7b$;?/EK(/kJ`:S`lrG#gcCE_``YgR_&MbQi0?hIKA<l0-PGTJ@p^ZZ\@k'd'#oDmk<-&+4i:9qnl>.._q_DlLGLZW_7)cqhnPjEQ.&E*1CLrKXYWjF\>9V`/nD*&oPn$bH$6_L[V,C9q\H^V@2d4hWZH4hKQ6cclC5Dd-!*c_ejm0cT%&BS+^2"JM?,j*rhk\5G,Qnb%[!@i7n05A\d^UQPRA0~>endstream
|
||||||
|
endobj
|
||||||
|
15 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1422
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Gau0B?#SIW&:ErMfXGo3#pY<?,o%g<\b6(E&-TPE+8nN![#\jJKbTMOIslMi\$G%iDK7<1,dq1./8&U.aW\MC*e'Fb_!c?S]]R">R'2#f/:mU+r%W[7T#^UO4I7UkT(<sj.[_jIJjYj%N#/dMGltCbc<F+fXY'1QG>NL\4bNRF0`Q8;QNpd3ic!f8X#u@S_S*StO1mFi@?8fJE7O]j.Fhh;eq%+_P\Vhk6)A"2EI7Sm*'AZa!1kScMc_SXb)hI5nP$m[O:.Xkn@($^[T1=-eWq,R?\kYfB(/hgUK[-MNBUl7`f6`"o&G4;5a82bMm^XQ+Arr7!fPaSe;ZPF`]J81of;ZQX1T>*ip7@PPd3E;q*anlW--k*_3E;Ci=u]#,=P`ckKIZg+'$^e>#e%a-BSIE1)9$p#pBhjquYu+eNft8/(>'b-r[`VTNT9t4;-!*^/Ce)odQ<*'MLn4T4%)=0t,)!D*\5dSp.WD]/@_-9%V3fZ6Y^gMd?4Hf5@rH[@V,9ebT:gI#hV:i3P&-MMhV\Z=7V^B5k7Ym@`%ZCr"el9Eu&V,RTZ"RMSXeEpOD=N,COJ?Y`c""LFt@HE5d-7mdgI,Pj'aZI/'4mF2$'#dT[@6LY)/469kL*@;1i+/2kkGd>kQ(`6,bB8ePG9?uP(a:Eg)]/FoBeZ^mAKq:W56BtT[CBm3OC@PSfcDaN2LJS0s4Q2[V/P2.b7;,RKi!4Bb'eq5K#f/NZ);LV!%-jn&r_K/3cE\^Q&(J06\^a`IfF6lbcM,7TTmS#0*MuHZ)=30Z92CISkkq*o%&f+(BT/QXQ\daq==SN!k,ZIClc]u9VYn=qUKVDJdFsY.EeKkq&IU8c;/\gbCWsU\do"8;3fF@Q[=VsD`>/P'3!)"9n2&2G3(a_O0sr?`p#KS&R57-lOMLYCU",g1;B5YHpSKjlELXYeBo.dOP[s:pFBX:Yc*Pf2K#)e==(1fGJo0GT=4n!0SRkZ?30Y@!CtD%X#P?GR[X#n0BCH\lA-#e9gkP!"NPkZ($ch!0ePl#IZnL".dNIKP9B/]07D))W<CkbX>E.JK97qE?!G1HMb;aK#M_mH<cM'<!g=/ZK*ZfKk.>+L=47bJTd4[PIFM@iu8=0DuWb_+iis13LS?FXK:5snA(!^lL(pb;G^W"*\UC`gGQulgZNpDmD,<C.[<j`6,PX^*(mm*C1H4Cg&m.#=MpGs%&g0>oo`ToA94][:aefW/[[p1mi-Q&UI4GrZAUXl<mT>759(^tl++*@sBQ\pm',`5Ucc-QQN+2k4Dhr7(9^B<ie%SW[<c>oM;1&$5SLe(0%%/[EqlVPYpHg3A>K]psR%ce&sJ6--#jJPi*^$c@kefZ=HE,ct8&BfZ62$1!#'Ru?sG)'Z6I[RtT>[_qqa(@PWVg]A*r%l1.cNI$=J]!u'N7!,N~>endstream
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 16
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000073 00000 n
|
||||||
|
0000000124 00000 n
|
||||||
|
0000000231 00000 n
|
||||||
|
0000000343 00000 n
|
||||||
|
0000000426 00000 n
|
||||||
|
0000000631 00000 n
|
||||||
|
0000000836 00000 n
|
||||||
|
0000001041 00000 n
|
||||||
|
0000001246 00000 n
|
||||||
|
0000001315 00000 n
|
||||||
|
0000001612 00000 n
|
||||||
|
0000001690 00000 n
|
||||||
|
0000004191 00000 n
|
||||||
|
0000005127 00000 n
|
||||||
|
0000006050 00000 n
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/ID
|
||||||
|
[<2232646b4bd42a525eb8afd576232bc1><2232646b4bd42a525eb8afd576232bc1>]
|
||||||
|
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
|
||||||
|
|
||||||
|
/Info 10 0 R
|
||||||
|
/Root 9 0 R
|
||||||
|
/Size 16
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
7564
|
||||||
|
%%EOF
|
||||||
BIN
activite1/knn_activite_latex.pdf
Normal file
BIN
activite1/knn_activite_latex.pdf
Normal file
Binary file not shown.
561
activite1/knn_corse_interactive.ipynb
Normal file
561
activite1/knn_corse_interactive.ipynb
Normal file
|
|
@ -0,0 +1,561 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# 🗺️ Classification k-NN : Haute-Corse ou Corse du Sud ?\n",
|
||||||
|
"\n",
|
||||||
|
"## Objectif\n",
|
||||||
|
"Utiliser l'algorithme des **k plus proches voisins (k-NN)** pour déterminer si un point de la carte de Corse se situe en **Haute-Corse (2B)** ou en **Corse du Sud (2A)**, en se basant sur les villages les plus proches.\n",
|
||||||
|
"\n",
|
||||||
|
"## Principe\n",
|
||||||
|
"1. On charge les données des villages corses avec leurs coordonnées GPS et leur département\n",
|
||||||
|
"2. On choisit un point sur la carte\n",
|
||||||
|
"3. On calcule les distances entre ce point et tous les villages\n",
|
||||||
|
"4. On identifie les k villages les plus proches\n",
|
||||||
|
"5. On vote : le département majoritaire parmi ces k villages devient la prédiction"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📦 Installation et imports"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques nécessaires (si besoin)\n",
|
||||||
|
"import sys\n",
|
||||||
|
"!{sys.executable} -m pip install folium pandas numpy -q"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import folium\n",
|
||||||
|
"from folium.plugins import MarkerCluster\n",
|
||||||
|
"import math\n",
|
||||||
|
"from collections import Counter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📊 Chargement des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Charger le fichier CSV\n",
|
||||||
|
"# Remplacez 'villages_corse.csv' par le chemin de votre fichier\n",
|
||||||
|
"df = pd.read_csv('villages_corse.csv', sep=';', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher les premières lignes\n",
|
||||||
|
"print(f\"Nombre de villages : {len(df)}\")\n",
|
||||||
|
"df.head()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🔧 Préparation des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def parse_coordinates(point_geo_str):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Parse la colonne Point_Geo pour extraire latitude et longitude.\n",
|
||||||
|
" Format attendu : \"POINT(longitude latitude)\" ou similaire\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" try:\n",
|
||||||
|
" # Supprimer 'POINT(' et ')'\n",
|
||||||
|
" coords = point_geo_str.replace('POINT(', '').replace(')', '').strip()\n",
|
||||||
|
" lon, lat = coords.split()\n",
|
||||||
|
" return float(lat), float(lon)\n",
|
||||||
|
" except:\n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"# Extraire les coordonnées\n",
|
||||||
|
"df[['latitude', 'longitude']] = df['Point_Geo'].apply(\n",
|
||||||
|
" lambda x: pd.Series(parse_coordinates(x))\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Supprimer les lignes sans coordonnées valides\n",
|
||||||
|
"df = df.dropna(subset=['latitude', 'longitude'])\n",
|
||||||
|
"\n",
|
||||||
|
"# Simplifier les noms de départements\n",
|
||||||
|
"df['dept_simple'] = df['Code Département'].apply(lambda x: '2A' if x == '2A' else '2B')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Villages avec coordonnées valides : {len(df)}\")\n",
|
||||||
|
"print(f\"\\nRépartition par département :\")\n",
|
||||||
|
"print(df['dept_simple'].value_counts())\n",
|
||||||
|
"\n",
|
||||||
|
"df[['Nom français', 'dept_simple', 'latitude', 'longitude']].head()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📏 Fonction de calcul de distance\n",
|
||||||
|
"\n",
|
||||||
|
"Nous utilisons la **formule de Haversine** pour calculer la distance entre deux points GPS sur la surface de la Terre."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def haversine_distance(lat1, lon1, lat2, lon2):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Calcule la distance en kilomètres entre deux points GPS.\n",
|
||||||
|
" Formule de Haversine.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" R = 6371 # Rayon de la Terre en km\n",
|
||||||
|
" \n",
|
||||||
|
" # Conversion en radians\n",
|
||||||
|
" lat1_rad = math.radians(lat1)\n",
|
||||||
|
" lat2_rad = math.radians(lat2)\n",
|
||||||
|
" delta_lat = math.radians(lat2 - lat1)\n",
|
||||||
|
" delta_lon = math.radians(lon2 - lon1)\n",
|
||||||
|
" \n",
|
||||||
|
" # Formule de Haversine\n",
|
||||||
|
" a = math.sin(delta_lat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(delta_lon/2)**2\n",
|
||||||
|
" c = 2 * math.asin(math.sqrt(a))\n",
|
||||||
|
" \n",
|
||||||
|
" return R * c\n",
|
||||||
|
"\n",
|
||||||
|
"# Test de la fonction\n",
|
||||||
|
"# Distance entre Ajaccio et Bastia (environ 100 km)\n",
|
||||||
|
"dist_test = haversine_distance(41.9267, 8.7369, 42.7028, 9.4500)\n",
|
||||||
|
"print(f\"Distance Ajaccio-Bastia : {dist_test:.1f} km\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎯 Algorithme k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def knn_classify(test_lat, test_lon, df, k=5):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Classifie un point (test_lat, test_lon) en utilisant k-NN.\n",
|
||||||
|
" \n",
|
||||||
|
" Retourne :\n",
|
||||||
|
" - prediction : le département prédit ('2A' ou '2B')\n",
|
||||||
|
" - neighbors : DataFrame des k plus proches voisins\n",
|
||||||
|
" - votes : dictionnaire des votes\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Calculer les distances pour tous les villages\n",
|
||||||
|
" distances = []\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" dist = haversine_distance(test_lat, test_lon, row['latitude'], row['longitude'])\n",
|
||||||
|
" distances.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'departement': row['dept_simple'],\n",
|
||||||
|
" 'latitude': row['latitude'],\n",
|
||||||
|
" 'longitude': row['longitude'],\n",
|
||||||
|
" 'distance': dist\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer un DataFrame et trier par distance\n",
|
||||||
|
" dist_df = pd.DataFrame(distances)\n",
|
||||||
|
" dist_df = dist_df.sort_values('distance')\n",
|
||||||
|
" \n",
|
||||||
|
" # Sélectionner les k plus proches\n",
|
||||||
|
" neighbors = dist_df.head(k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Voter\n",
|
||||||
|
" votes = Counter(neighbors['departement'])\n",
|
||||||
|
" prediction = votes.most_common(1)[0][0]\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction, neighbors, votes\n",
|
||||||
|
"\n",
|
||||||
|
"# Test de l'algorithme avec un point au centre de la Corse\n",
|
||||||
|
"test_lat, test_lon = 42.15, 9.05\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"\\n🎯 Point de test : ({test_lat}, {test_lon})\")\n",
|
||||||
|
"print(f\"\\nAvec k={k} :\")\n",
|
||||||
|
"print(f\"Prédiction : {prediction}\")\n",
|
||||||
|
"print(f\"Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\nLes {k} plus proches voisins :\")\n",
|
||||||
|
"print(neighbors[['village', 'departement', 'distance']])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🗺️ Visualisation avec Folium"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def create_map(test_lat=None, test_lon=None, k=5, show_all_villages=False):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Crée une carte interactive avec Folium.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Centre de la Corse\n",
|
||||||
|
" center_lat = 42.15\n",
|
||||||
|
" center_lon = 9.05\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer la carte\n",
|
||||||
|
" m = folium.Map(\n",
|
||||||
|
" location=[center_lat, center_lon],\n",
|
||||||
|
" zoom_start=9,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher tous les villages (optionnel, peut être lourd)\n",
|
||||||
|
" if show_all_villages:\n",
|
||||||
|
" marker_cluster = MarkerCluster().add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['latitude'], row['longitude']],\n",
|
||||||
|
" radius=2,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color,\n",
|
||||||
|
" fillOpacity=0.3,\n",
|
||||||
|
" popup=f\"{row['Nom français']} ({row['dept_simple']})\"\n",
|
||||||
|
" ).add_to(marker_cluster)\n",
|
||||||
|
" \n",
|
||||||
|
" # Si un point de test est fourni\n",
|
||||||
|
" if test_lat is not None and test_lon is not None:\n",
|
||||||
|
" # Classification\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur pour le point de test\n",
|
||||||
|
" color = 'darkred' if prediction == '2A' else 'darkblue'\n",
|
||||||
|
" folium.Marker(\n",
|
||||||
|
" location=[test_lat, test_lon],\n",
|
||||||
|
" popup=f\"Point à classifier<br>Prédiction : {prediction}<br>Votes : {dict(votes)}\",\n",
|
||||||
|
" icon=folium.Icon(color=color, icon='star', prefix='fa')\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les k plus proches voisins\n",
|
||||||
|
" for idx, neighbor in neighbors.iterrows():\n",
|
||||||
|
" # Marqueur pour chaque voisin\n",
|
||||||
|
" color = 'red' if neighbor['departement'] == '2A' else 'blue'\n",
|
||||||
|
" folium.Marker(\n",
|
||||||
|
" location=[neighbor['latitude'], neighbor['longitude']],\n",
|
||||||
|
" popup=f\"{neighbor['village']}<br>{neighbor['departement']}<br>Distance: {neighbor['distance']:.2f} km\",\n",
|
||||||
|
" icon=folium.Icon(color=color, icon='info-sign')\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Ligne entre le point test et le voisin\n",
|
||||||
|
" folium.PolyLine(\n",
|
||||||
|
" locations=[\n",
|
||||||
|
" [test_lat, test_lon],\n",
|
||||||
|
" [neighbor['latitude'], neighbor['longitude']]\n",
|
||||||
|
" ],\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" weight=2,\n",
|
||||||
|
" opacity=0.5\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Légende\n",
|
||||||
|
" legend_html = '''\n",
|
||||||
|
" <div style=\"position: fixed; \n",
|
||||||
|
" bottom: 50px; right: 50px; width: 200px; height: 120px; \n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; \n",
|
||||||
|
" font-size:14px; padding: 10px\">\n",
|
||||||
|
" <p><strong>Légende</strong></p>\n",
|
||||||
|
" <p><i class=\"fa fa-circle\" style=\"color:red\"></i> Corse du Sud (2A)</p>\n",
|
||||||
|
" <p><i class=\"fa fa-circle\" style=\"color:blue\"></i> Haute-Corse (2B)</p>\n",
|
||||||
|
" <p><i class=\"fa fa-star\" style=\"color:darkred\"></i> Point à classifier</p>\n",
|
||||||
|
" </div>\n",
|
||||||
|
" '''\n",
|
||||||
|
" m.get_root().html.add_child(folium.Element(legend_html))\n",
|
||||||
|
" \n",
|
||||||
|
" return m\n",
|
||||||
|
"\n",
|
||||||
|
"# Créer la carte avec le point de test\n",
|
||||||
|
"map_with_test = create_map(test_lat=42.15, test_lon=9.05, k=5, show_all_villages=False)\n",
|
||||||
|
"map_with_test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🔬 Expérimentation : Influence de k"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Test avec différentes valeurs de k\n",
|
||||||
|
"test_point = (42.15, 9.05) # Point au centre de la Corse\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Point testé : {test_point}\\n\")\n",
|
||||||
|
"print(f\"{'k':<5} {'Prédiction':<12} {'Votes 2A':<10} {'Votes 2B':<10}\")\n",
|
||||||
|
"print(\"-\" * 45)\n",
|
||||||
|
"\n",
|
||||||
|
"for k in [1, 3, 5, 7, 9, 15]:\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(test_point[0], test_point[1], df, k=k)\n",
|
||||||
|
" votes_2a = votes.get('2A', 0)\n",
|
||||||
|
" votes_2b = votes.get('2B', 0)\n",
|
||||||
|
" print(f\"{k:<5} {prediction:<12} {votes_2a:<10} {votes_2b:<10}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎮 Mode interactif : Testez vos propres points !\n",
|
||||||
|
"\n",
|
||||||
|
"Modifiez les coordonnées ci-dessous pour tester différents points de la Corse."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# === MODIFIEZ CES VALEURS ===\n",
|
||||||
|
"test_latitude = 42.5 # Entre 41.3 (sud) et 43.0 (nord)\n",
|
||||||
|
"test_longitude = 9.2 # Entre 8.5 (ouest) et 9.5 (est)\n",
|
||||||
|
"k_value = 7 # Nombre de voisins\n",
|
||||||
|
"# =============================\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_latitude, test_longitude, df, k=k_value)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"📍 Point : ({test_latitude}, {test_longitude})\")\n",
|
||||||
|
"print(f\"🔢 k = {k_value}\")\n",
|
||||||
|
"print(f\"\\n🎯 Prédiction : {'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'}\")\n",
|
||||||
|
"print(f\"\\n📊 Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\n🏘️ Les {k_value} plus proches villages :\")\n",
|
||||||
|
"print(neighbors[['village', 'departement', 'distance']].to_string(index=False))\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher la carte\n",
|
||||||
|
"map_interactive = create_map(test_latitude, test_longitude, k=k_value, show_all_villages=False)\n",
|
||||||
|
"map_interactive"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🌍 Carte complète avec tous les villages"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Afficher tous les villages de Corse (peut être lent)\n",
|
||||||
|
"# Attention : cette cellule peut prendre du temps à s'exécuter\n",
|
||||||
|
"\n",
|
||||||
|
"map_all = create_map(show_all_villages=True)\n",
|
||||||
|
"map_all"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📈 Visualisation de la frontière entre départements"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Créer une grille de points et classifier chacun\n",
|
||||||
|
"# Cela permet de visualiser la \"frontière\" selon k-NN\n",
|
||||||
|
"\n",
|
||||||
|
"def create_decision_boundary_map(k=5, grid_resolution=50):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Crée une carte montrant la frontière de décision de k-NN.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Limites de la Corse\n",
|
||||||
|
" lat_min, lat_max = 41.3, 43.0\n",
|
||||||
|
" lon_min, lon_max = 8.5, 9.6\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer une grille\n",
|
||||||
|
" lats = np.linspace(lat_min, lat_max, grid_resolution)\n",
|
||||||
|
" lons = np.linspace(lon_min, lon_max, grid_resolution)\n",
|
||||||
|
" \n",
|
||||||
|
" m = folium.Map(\n",
|
||||||
|
" location=[42.15, 9.05],\n",
|
||||||
|
" zoom_start=8,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" # Classifier chaque point de la grille\n",
|
||||||
|
" print(\"Classification de la grille en cours...\")\n",
|
||||||
|
" for i, lat in enumerate(lats[::5]): # Réduire la résolution pour la vitesse\n",
|
||||||
|
" for lon in lons[::5]:\n",
|
||||||
|
" prediction, _, _ = knn_classify(lat, lon, df, k=k)\n",
|
||||||
|
" color = 'red' if prediction == '2A' else 'blue'\n",
|
||||||
|
" \n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[lat, lon],\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color,\n",
|
||||||
|
" fillOpacity=0.2,\n",
|
||||||
|
" weight=0\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" if (i+1) % 5 == 0:\n",
|
||||||
|
" print(f\" {(i+1)*100//len(lats[::5])}% complété\")\n",
|
||||||
|
" \n",
|
||||||
|
" print(\"Terminé !\")\n",
|
||||||
|
" return m\n",
|
||||||
|
"\n",
|
||||||
|
"# Créer la carte (peut prendre quelques secondes)\n",
|
||||||
|
"print(f\"Création de la carte de frontière avec k=5...\")\n",
|
||||||
|
"boundary_map = create_decision_boundary_map(k=5, grid_resolution=30)\n",
|
||||||
|
"boundary_map"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎓 Questions de réflexion\n",
|
||||||
|
"\n",
|
||||||
|
"1. **Influence de k** : Testez différentes valeurs de k (1, 3, 5, 10, 20). Comment la prédiction change-t-elle ?\n",
|
||||||
|
"\n",
|
||||||
|
"2. **Points frontières** : Trouvez des points où la classification change selon la valeur de k.\n",
|
||||||
|
"\n",
|
||||||
|
"3. **Zones ambiguës** : Où se situent les zones les plus difficiles à classifier ?\n",
|
||||||
|
"\n",
|
||||||
|
"4. **Validité** : Cette méthode est-elle toujours fiable ? Dans quels cas pourrait-elle échouer ?\n",
|
||||||
|
"\n",
|
||||||
|
"5. **Amélioration** : Comment pourrait-on améliorer l'algorithme ? (pondération par distance, normalisation, etc.)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 💡 Pour aller plus loin\n",
|
||||||
|
"\n",
|
||||||
|
"### Exercices supplémentaires :\n",
|
||||||
|
"\n",
|
||||||
|
"1. **Pondération par distance** : Modifier l'algorithme pour donner plus de poids aux villages plus proches\n",
|
||||||
|
"2. **Validation croisée** : Tester la précision en utilisant les villages eux-mêmes comme points de test\n",
|
||||||
|
"3. **Autres critères** : Ajouter l'altitude comme dimension supplémentaire\n",
|
||||||
|
"4. **Clustering** : Identifier des groupes de villages similaires"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# BONUS : Validation croisée\n",
|
||||||
|
"# Tester la précision en utilisant les villages eux-mêmes\n",
|
||||||
|
"\n",
|
||||||
|
"def cross_validation(df, k=5, sample_size=100):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Teste la précision de k-NN en utilisant un échantillon de villages.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Prendre un échantillon aléatoire\n",
|
||||||
|
" sample = df.sample(n=min(sample_size, len(df)), random_state=42)\n",
|
||||||
|
" \n",
|
||||||
|
" correct = 0\n",
|
||||||
|
" total = 0\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in sample.iterrows():\n",
|
||||||
|
" # Créer un dataset sans ce village\n",
|
||||||
|
" df_without = df.drop(idx)\n",
|
||||||
|
" \n",
|
||||||
|
" # Classifier ce village\n",
|
||||||
|
" prediction, _, _ = knn_classify(\n",
|
||||||
|
" row['latitude'], \n",
|
||||||
|
" row['longitude'], \n",
|
||||||
|
" df_without, \n",
|
||||||
|
" k=k\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" if prediction == row['dept_simple']:\n",
|
||||||
|
" correct += 1\n",
|
||||||
|
" total += 1\n",
|
||||||
|
" \n",
|
||||||
|
" accuracy = (correct / total) * 100\n",
|
||||||
|
" return accuracy, correct, total\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Test de précision de l'algorithme k-NN...\\n\")\n",
|
||||||
|
"\n",
|
||||||
|
"for k in [1, 3, 5, 10]:\n",
|
||||||
|
" accuracy, correct, total = cross_validation(df, k=k, sample_size=100)\n",
|
||||||
|
" print(f\"k={k:2d} : {accuracy:.1f}% de précision ({correct}/{total} corrects)\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
375
activite1/knn_corse_interactive_click(1).ipynb
Normal file
375
activite1/knn_corse_interactive_click(1).ipynb
Normal file
|
|
@ -0,0 +1,375 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# 🗺️ k-NN Corse : Version Interactive avec Clic sur Carte\n",
|
||||||
|
"\n",
|
||||||
|
"## 🎮 Mode d'emploi\n",
|
||||||
|
"1. Exécutez toutes les cellules\n",
|
||||||
|
"2. **Cliquez sur la carte** pour choisir un point\n",
|
||||||
|
"3. Ajustez k avec le curseur\n",
|
||||||
|
"4. Observez la classification en temps réel !"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📦 Installation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques\n",
|
||||||
|
"import sys\n",
|
||||||
|
"!{sys.executable} -m pip install ipyleaflet ipywidgets pandas numpy -q"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import math\n",
|
||||||
|
"from collections import Counter\n",
|
||||||
|
"from ipyleaflet import Map, Marker, CircleMarker, Polyline, AwesomeIcon, LayerGroup\n",
|
||||||
|
"from ipywidgets import HTML, VBox, HBox, IntSlider, Output, Label\n",
|
||||||
|
"from IPython.display import display, clear_output"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📊 Chargement des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Charger les données\n",
|
||||||
|
"df = pd.read_csv('villages_corse.csv', sep='\\t', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"def parse_coordinates(point_geo_str):\n",
|
||||||
|
" try:\n",
|
||||||
|
" parts = str(point_geo_str).split(',')\n",
|
||||||
|
" lat = float(parts[0].strip())\n",
|
||||||
|
" lon = float(parts[1].strip())\n",
|
||||||
|
" return lat, lon\n",
|
||||||
|
" except:\n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"df[['latitude', 'longitude']] = df['Point_Geo'].apply(\n",
|
||||||
|
" lambda x: pd.Series(parse_coordinates(x))\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"df = df.dropna(subset=['latitude', 'longitude'])\n",
|
||||||
|
"df['dept_simple'] = df['Code Département'].apply(lambda x: '2A' if str(x) == '2A' else '2B')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"✅ {len(df)} villages chargés\")\n",
|
||||||
|
"print(f\" - Corse du Sud (2A) : {len(df[df['dept_simple']=='2A'])}\")\n",
|
||||||
|
"print(f\" - Haute-Corse (2B) : {len(df[df['dept_simple']=='2B'])}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🧮 Fonctions k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def haversine_distance(lat1, lon1, lat2, lon2):\n",
|
||||||
|
" \"\"\"Calcule la distance en km entre deux points GPS.\"\"\"\n",
|
||||||
|
" R = 6371\n",
|
||||||
|
" lat1_rad = math.radians(lat1)\n",
|
||||||
|
" lat2_rad = math.radians(lat2)\n",
|
||||||
|
" delta_lat = math.radians(lat2 - lat1)\n",
|
||||||
|
" delta_lon = math.radians(lon2 - lon1)\n",
|
||||||
|
" \n",
|
||||||
|
" a = math.sin(delta_lat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(delta_lon/2)**2\n",
|
||||||
|
" c = 2 * math.asin(math.sqrt(a))\n",
|
||||||
|
" \n",
|
||||||
|
" return R * c\n",
|
||||||
|
"\n",
|
||||||
|
"def knn_classify(test_lat, test_lon, df, k=5):\n",
|
||||||
|
" \"\"\"Classifie un point avec k-NN.\"\"\"\n",
|
||||||
|
" distances = []\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" dist = haversine_distance(test_lat, test_lon, row['latitude'], row['longitude'])\n",
|
||||||
|
" distances.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'nom_corse': row['Nom corse'],\n",
|
||||||
|
" 'departement': row['dept_simple'],\n",
|
||||||
|
" 'latitude': row['latitude'],\n",
|
||||||
|
" 'longitude': row['longitude'],\n",
|
||||||
|
" 'distance': dist\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" dist_df = pd.DataFrame(distances).sort_values('distance')\n",
|
||||||
|
" neighbors = dist_df.head(k)\n",
|
||||||
|
" votes = Counter(neighbors['departement'])\n",
|
||||||
|
" prediction = votes.most_common(1)[0][0]\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction, neighbors, votes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🗺️ Carte Interactive\n",
|
||||||
|
"\n",
|
||||||
|
"**Instructions :**\n",
|
||||||
|
"- 🖱️ **Cliquez sur la carte** pour placer un point\n",
|
||||||
|
"- 🎚️ **Ajustez k** avec le curseur\n",
|
||||||
|
"- 👁️ La classification se met à jour automatiquement"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Créer la carte\n",
|
||||||
|
"m = Map(center=(42.15, 9.05), zoom=9, scroll_wheel_zoom=True)\n",
|
||||||
|
"\n",
|
||||||
|
"# Couches pour les éléments dynamiques\n",
|
||||||
|
"test_point_layer = LayerGroup()\n",
|
||||||
|
"neighbors_layer = LayerGroup()\n",
|
||||||
|
"lines_layer = LayerGroup()\n",
|
||||||
|
"\n",
|
||||||
|
"m.add_layer(test_point_layer)\n",
|
||||||
|
"m.add_layer(neighbors_layer)\n",
|
||||||
|
"m.add_layer(lines_layer)\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher quelques villages de référence\n",
|
||||||
|
"sample_villages = df.sample(n=min(50, len(df)), random_state=42)\n",
|
||||||
|
"for idx, row in sample_villages.iterrows():\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" circle = CircleMarker(\n",
|
||||||
|
" location=(row['latitude'], row['longitude']),\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill_color=color,\n",
|
||||||
|
" fill_opacity=0.4,\n",
|
||||||
|
" weight=1\n",
|
||||||
|
" )\n",
|
||||||
|
" m.add_layer(circle)\n",
|
||||||
|
"\n",
|
||||||
|
"# Widget pour k\n",
|
||||||
|
"k_slider = IntSlider(\n",
|
||||||
|
" value=5,\n",
|
||||||
|
" min=1,\n",
|
||||||
|
" max=20,\n",
|
||||||
|
" step=1,\n",
|
||||||
|
" description='k:',\n",
|
||||||
|
" continuous_update=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Zone de résultats\n",
|
||||||
|
"result_output = Output()\n",
|
||||||
|
"info_html = HTML(value=\"<p style='font-size:16px; padding:10px; background:#f0f0f0; border-radius:5px;'>👆 <b>Cliquez sur la carte pour classifier un point</b></p>\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Variable globale pour stocker les coordonnées\n",
|
||||||
|
"current_coords = {'lat': None, 'lon': None}\n",
|
||||||
|
"\n",
|
||||||
|
"def update_classification(lat, lon, k):\n",
|
||||||
|
" \"\"\"Met à jour la classification et la visualisation.\"\"\"\n",
|
||||||
|
" # Effacer les couches précédentes\n",
|
||||||
|
" test_point_layer.clear_layers()\n",
|
||||||
|
" neighbors_layer.clear_layers()\n",
|
||||||
|
" lines_layer.clear_layers()\n",
|
||||||
|
" \n",
|
||||||
|
" # Classification\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(lat, lon, df, k=k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Couleur selon prédiction\n",
|
||||||
|
" color = 'red' if prediction == '2A' else 'blue'\n",
|
||||||
|
" dept_name = 'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur du point test\n",
|
||||||
|
" icon = AwesomeIcon(\n",
|
||||||
|
" name='star',\n",
|
||||||
|
" marker_color='darkred' if prediction == '2A' else 'darkblue',\n",
|
||||||
|
" icon_color='white'\n",
|
||||||
|
" )\n",
|
||||||
|
" test_marker = Marker(location=(lat, lon), icon=icon, draggable=False)\n",
|
||||||
|
" test_point_layer.add_layer(test_marker)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les k plus proches voisins\n",
|
||||||
|
" for idx, neighbor in neighbors.iterrows():\n",
|
||||||
|
" n_color = 'red' if neighbor['departement'] == '2A' else 'blue'\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur du voisin\n",
|
||||||
|
" n_marker = CircleMarker(\n",
|
||||||
|
" location=(neighbor['latitude'], neighbor['longitude']),\n",
|
||||||
|
" radius=8,\n",
|
||||||
|
" color=n_color,\n",
|
||||||
|
" fill_color=n_color,\n",
|
||||||
|
" fill_opacity=0.7,\n",
|
||||||
|
" weight=2\n",
|
||||||
|
" )\n",
|
||||||
|
" neighbors_layer.add_layer(n_marker)\n",
|
||||||
|
" \n",
|
||||||
|
" # Ligne vers le voisin\n",
|
||||||
|
" line = Polyline(\n",
|
||||||
|
" locations=[\n",
|
||||||
|
" (lat, lon),\n",
|
||||||
|
" (neighbor['latitude'], neighbor['longitude'])\n",
|
||||||
|
" ],\n",
|
||||||
|
" color=n_color,\n",
|
||||||
|
" weight=2,\n",
|
||||||
|
" opacity=0.5\n",
|
||||||
|
" )\n",
|
||||||
|
" lines_layer.add_layer(line)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les résultats\n",
|
||||||
|
" with result_output:\n",
|
||||||
|
" clear_output(wait=True)\n",
|
||||||
|
" print(f\"📍 Coordonnées : ({lat:.4f}, {lon:.4f})\")\n",
|
||||||
|
" print(f\"🔢 k = {k}\")\n",
|
||||||
|
" print(f\"\\n🎯 Prédiction : {dept_name}\")\n",
|
||||||
|
" print(f\"📊 Votes : 2A={votes.get('2A', 0)}, 2B={votes.get('2B', 0)}\")\n",
|
||||||
|
" print(f\"\\n🏘️ Les {k} plus proches villages :\")\n",
|
||||||
|
" print(neighbors[['village', 'nom_corse', 'departement', 'distance']].to_string(index=False))\n",
|
||||||
|
" \n",
|
||||||
|
" # Mettre à jour l'info\n",
|
||||||
|
" info_html.value = f\"<div style='font-size:16px; padding:10px; background:{'#ffebee' if prediction=='2A' else '#e3f2fd'}; border-radius:5px; border-left: 4px solid {color};'><b>Classification : {dept_name}</b><br>Votes : 2A={votes.get('2A', 0)}, 2B={votes.get('2B', 0)}</div>\"\n",
|
||||||
|
"\n",
|
||||||
|
"def handle_click(**kwargs):\n",
|
||||||
|
" \"\"\"Gestionnaire de clic sur la carte.\"\"\"\n",
|
||||||
|
" if kwargs.get('type') == 'click':\n",
|
||||||
|
" coords = kwargs.get('coordinates')\n",
|
||||||
|
" lat, lon = coords\n",
|
||||||
|
" current_coords['lat'] = lat\n",
|
||||||
|
" current_coords['lon'] = lon\n",
|
||||||
|
" update_classification(lat, lon, k_slider.value)\n",
|
||||||
|
"\n",
|
||||||
|
"def on_k_change(change):\n",
|
||||||
|
" \"\"\"Gestionnaire de changement de k.\"\"\"\n",
|
||||||
|
" if current_coords['lat'] is not None:\n",
|
||||||
|
" update_classification(current_coords['lat'], current_coords['lon'], change['new'])\n",
|
||||||
|
"\n",
|
||||||
|
"# Connecter les événements\n",
|
||||||
|
"m.on_interaction(handle_click)\n",
|
||||||
|
"k_slider.observe(on_k_change, names='value')\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher l'interface\n",
|
||||||
|
"display(VBox([\n",
|
||||||
|
" info_html,\n",
|
||||||
|
" HBox([Label('Nombre de voisins (k):'), k_slider]),\n",
|
||||||
|
" m,\n",
|
||||||
|
" result_output\n",
|
||||||
|
"]))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎯 Points d'intérêt à tester\n",
|
||||||
|
"\n",
|
||||||
|
"Essayez de cliquer sur ces zones :\n",
|
||||||
|
"\n",
|
||||||
|
"- **Ajaccio** : (41.9267, 8.7369) - Capitale 2A\n",
|
||||||
|
"- **Bastia** : (42.7028, 9.4500) - Préfecture 2B\n",
|
||||||
|
"- **Corte** : (42.3062, 9.1509) - Centre de la Corse\n",
|
||||||
|
"- **Frontière approximative** : Zone entre 42.0 et 42.3 latitude\n",
|
||||||
|
"\n",
|
||||||
|
"### Questions à explorer :\n",
|
||||||
|
"1. 🤔 Où se situe la \"frontière\" k-NN entre les deux départements ?\n",
|
||||||
|
"2. 📊 Comment k influence-t-il la classification près de cette frontière ?\n",
|
||||||
|
"3. 🏔️ Y a-t-il des zones ambiguës où le résultat change souvent ?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 💡 Mode manuel (si la carte ne fonctionne pas)\n",
|
||||||
|
"\n",
|
||||||
|
"Si le clic sur carte ne fonctionne pas, utilisez cette cellule :"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Mode manuel : entrez les coordonnées\n",
|
||||||
|
"test_lat = 42.3 # Modifiez ici\n",
|
||||||
|
"test_lon = 9.15 # Modifiez ici\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
"dept_name = 'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"📍 Point : ({test_lat}, {test_lon})\")\n",
|
||||||
|
"print(f\"🎯 Prédiction : {dept_name}\")\n",
|
||||||
|
"print(f\"📊 Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\n🏘️ Les {k} plus proches villages :\")\n",
|
||||||
|
"print(neighbors[['village', 'nom_corse', 'departement', 'distance']].to_string(index=False))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📝 Notes techniques\n",
|
||||||
|
"\n",
|
||||||
|
"Cette version utilise **ipyleaflet** qui offre une vraie interactivité bidirectionnelle entre Python et JavaScript dans Jupyter.\n",
|
||||||
|
"\n",
|
||||||
|
"**Avantages :**\n",
|
||||||
|
"- ✅ Clic directement sur la carte\n",
|
||||||
|
"- ✅ Mise à jour en temps réel\n",
|
||||||
|
"- ✅ Curseur interactif pour k\n",
|
||||||
|
"- ✅ Pas besoin de recharger\n",
|
||||||
|
"\n",
|
||||||
|
"**Prérequis :**\n",
|
||||||
|
"- Jupyter Notebook ou JupyterLab\n",
|
||||||
|
"- Extension widgets activée : `jupyter nbextension enable --py widgetsnbextension`"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
375
activite1/knn_corse_interactive_click.ipynb
Normal file
375
activite1/knn_corse_interactive_click.ipynb
Normal file
|
|
@ -0,0 +1,375 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# 🗺️ k-NN Corse : Version Interactive avec Clic sur Carte\n",
|
||||||
|
"\n",
|
||||||
|
"## 🎮 Mode d'emploi\n",
|
||||||
|
"1. Exécutez toutes les cellules\n",
|
||||||
|
"2. **Cliquez sur la carte** pour choisir un point\n",
|
||||||
|
"3. Ajustez k avec le curseur\n",
|
||||||
|
"4. Observez la classification en temps réel !"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📦 Installation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques\n",
|
||||||
|
"import sys\n",
|
||||||
|
"!{sys.executable} -m pip install ipyleaflet ipywidgets pandas numpy -q"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import math\n",
|
||||||
|
"from collections import Counter\n",
|
||||||
|
"from ipyleaflet import Map, Marker, CircleMarker, Polyline, AwesomeIcon, LayerGroup\n",
|
||||||
|
"from ipywidgets import HTML, VBox, HBox, IntSlider, Output, Label\n",
|
||||||
|
"from IPython.display import display, clear_output"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📊 Chargement des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Charger les données\n",
|
||||||
|
"df = pd.read_csv('villages_corse.csv', sep='\\t', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"def parse_coordinates(point_geo_str):\n",
|
||||||
|
" try:\n",
|
||||||
|
" parts = str(point_geo_str).split(',')\n",
|
||||||
|
" lat = float(parts[0].strip())\n",
|
||||||
|
" lon = float(parts[1].strip())\n",
|
||||||
|
" return lat, lon\n",
|
||||||
|
" except:\n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"df[['latitude', 'longitude']] = df['Point_Geo'].apply(\n",
|
||||||
|
" lambda x: pd.Series(parse_coordinates(x))\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"df = df.dropna(subset=['latitude', 'longitude'])\n",
|
||||||
|
"df['dept_simple'] = df['Code Département'].apply(lambda x: '2A' if str(x) == '2A' else '2B')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"✅ {len(df)} villages chargés\")\n",
|
||||||
|
"print(f\" - Corse du Sud (2A) : {len(df[df['dept_simple']=='2A'])}\")\n",
|
||||||
|
"print(f\" - Haute-Corse (2B) : {len(df[df['dept_simple']=='2B'])}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🧮 Fonctions k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def haversine_distance(lat1, lon1, lat2, lon2):\n",
|
||||||
|
" \"\"\"Calcule la distance en km entre deux points GPS.\"\"\"\n",
|
||||||
|
" R = 6371\n",
|
||||||
|
" lat1_rad = math.radians(lat1)\n",
|
||||||
|
" lat2_rad = math.radians(lat2)\n",
|
||||||
|
" delta_lat = math.radians(lat2 - lat1)\n",
|
||||||
|
" delta_lon = math.radians(lon2 - lon1)\n",
|
||||||
|
" \n",
|
||||||
|
" a = math.sin(delta_lat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(delta_lon/2)**2\n",
|
||||||
|
" c = 2 * math.asin(math.sqrt(a))\n",
|
||||||
|
" \n",
|
||||||
|
" return R * c\n",
|
||||||
|
"\n",
|
||||||
|
"def knn_classify(test_lat, test_lon, df, k=5):\n",
|
||||||
|
" \"\"\"Classifie un point avec k-NN.\"\"\"\n",
|
||||||
|
" distances = []\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" dist = haversine_distance(test_lat, test_lon, row['latitude'], row['longitude'])\n",
|
||||||
|
" distances.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'nom_corse': row['Nom corse'],\n",
|
||||||
|
" 'departement': row['dept_simple'],\n",
|
||||||
|
" 'latitude': row['latitude'],\n",
|
||||||
|
" 'longitude': row['longitude'],\n",
|
||||||
|
" 'distance': dist\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" dist_df = pd.DataFrame(distances).sort_values('distance')\n",
|
||||||
|
" neighbors = dist_df.head(k)\n",
|
||||||
|
" votes = Counter(neighbors['departement'])\n",
|
||||||
|
" prediction = votes.most_common(1)[0][0]\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction, neighbors, votes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🗺️ Carte Interactive\n",
|
||||||
|
"\n",
|
||||||
|
"**Instructions :**\n",
|
||||||
|
"- 🖱️ **Cliquez sur la carte** pour placer un point\n",
|
||||||
|
"- 🎚️ **Ajustez k** avec le curseur\n",
|
||||||
|
"- 👁️ La classification se met à jour automatiquement"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Créer la carte\n",
|
||||||
|
"m = Map(center=(42.15, 9.05), zoom=9, scroll_wheel_zoom=True)\n",
|
||||||
|
"\n",
|
||||||
|
"# Couches pour les éléments dynamiques\n",
|
||||||
|
"test_point_layer = LayerGroup()\n",
|
||||||
|
"neighbors_layer = LayerGroup()\n",
|
||||||
|
"lines_layer = LayerGroup()\n",
|
||||||
|
"\n",
|
||||||
|
"m.add_layer(test_point_layer)\n",
|
||||||
|
"m.add_layer(neighbors_layer)\n",
|
||||||
|
"m.add_layer(lines_layer)\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher quelques villages de référence\n",
|
||||||
|
"sample_villages = df.sample(n=min(50, len(df)), random_state=42)\n",
|
||||||
|
"for idx, row in sample_villages.iterrows():\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" circle = CircleMarker(\n",
|
||||||
|
" location=(row['latitude'], row['longitude']),\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill_color=color,\n",
|
||||||
|
" fill_opacity=0.4,\n",
|
||||||
|
" weight=1\n",
|
||||||
|
" )\n",
|
||||||
|
" m.add_layer(circle)\n",
|
||||||
|
"\n",
|
||||||
|
"# Widget pour k\n",
|
||||||
|
"k_slider = IntSlider(\n",
|
||||||
|
" value=5,\n",
|
||||||
|
" min=1,\n",
|
||||||
|
" max=20,\n",
|
||||||
|
" step=1,\n",
|
||||||
|
" description='k:',\n",
|
||||||
|
" continuous_update=False\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Zone de résultats\n",
|
||||||
|
"result_output = Output()\n",
|
||||||
|
"info_html = HTML(value=\"<p style='font-size:16px; padding:10px; background:#f0f0f0; border-radius:5px;'>👆 <b>Cliquez sur la carte pour classifier un point</b></p>\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Variable globale pour stocker les coordonnées\n",
|
||||||
|
"current_coords = {'lat': None, 'lon': None}\n",
|
||||||
|
"\n",
|
||||||
|
"def update_classification(lat, lon, k):\n",
|
||||||
|
" \"\"\"Met à jour la classification et la visualisation.\"\"\"\n",
|
||||||
|
" # Effacer les couches précédentes\n",
|
||||||
|
" test_point_layer.clear_layers()\n",
|
||||||
|
" neighbors_layer.clear_layers()\n",
|
||||||
|
" lines_layer.clear_layers()\n",
|
||||||
|
" \n",
|
||||||
|
" # Classification\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(lat, lon, df, k=k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Couleur selon prédiction\n",
|
||||||
|
" color = 'red' if prediction == '2A' else 'blue'\n",
|
||||||
|
" dept_name = 'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur du point test\n",
|
||||||
|
" icon = AwesomeIcon(\n",
|
||||||
|
" name='star',\n",
|
||||||
|
" marker_color='darkred' if prediction == '2A' else 'darkblue',\n",
|
||||||
|
" icon_color='white'\n",
|
||||||
|
" )\n",
|
||||||
|
" test_marker = Marker(location=(lat, lon), icon=icon, draggable=False)\n",
|
||||||
|
" test_point_layer.add_layer(test_marker)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les k plus proches voisins\n",
|
||||||
|
" for idx, neighbor in neighbors.iterrows():\n",
|
||||||
|
" n_color = 'red' if neighbor['departement'] == '2A' else 'blue'\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur du voisin\n",
|
||||||
|
" n_marker = CircleMarker(\n",
|
||||||
|
" location=(neighbor['latitude'], neighbor['longitude']),\n",
|
||||||
|
" radius=8,\n",
|
||||||
|
" color=n_color,\n",
|
||||||
|
" fill_color=n_color,\n",
|
||||||
|
" fill_opacity=0.7,\n",
|
||||||
|
" weight=2\n",
|
||||||
|
" )\n",
|
||||||
|
" neighbors_layer.add_layer(n_marker)\n",
|
||||||
|
" \n",
|
||||||
|
" # Ligne vers le voisin\n",
|
||||||
|
" line = Polyline(\n",
|
||||||
|
" locations=[\n",
|
||||||
|
" (lat, lon),\n",
|
||||||
|
" (neighbor['latitude'], neighbor['longitude'])\n",
|
||||||
|
" ],\n",
|
||||||
|
" color=n_color,\n",
|
||||||
|
" weight=2,\n",
|
||||||
|
" opacity=0.5\n",
|
||||||
|
" )\n",
|
||||||
|
" lines_layer.add_layer(line)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les résultats\n",
|
||||||
|
" with result_output:\n",
|
||||||
|
" clear_output(wait=True)\n",
|
||||||
|
" print(f\"📍 Coordonnées : ({lat:.4f}, {lon:.4f})\")\n",
|
||||||
|
" print(f\"🔢 k = {k}\")\n",
|
||||||
|
" print(f\"\\n🎯 Prédiction : {dept_name}\")\n",
|
||||||
|
" print(f\"📊 Votes : 2A={votes.get('2A', 0)}, 2B={votes.get('2B', 0)}\")\n",
|
||||||
|
" print(f\"\\n🏘️ Les {k} plus proches villages :\")\n",
|
||||||
|
" print(neighbors[['village', 'nom_corse', 'departement', 'distance']].to_string(index=False))\n",
|
||||||
|
" \n",
|
||||||
|
" # Mettre à jour l'info\n",
|
||||||
|
" info_html.value = f\"<div style='font-size:16px; padding:10px; background:{'#ffebee' if prediction=='2A' else '#e3f2fd'}; border-radius:5px; border-left: 4px solid {color};'><b>Classification : {dept_name}</b><br>Votes : 2A={votes.get('2A', 0)}, 2B={votes.get('2B', 0)}</div>\"\n",
|
||||||
|
"\n",
|
||||||
|
"def handle_click(**kwargs):\n",
|
||||||
|
" \"\"\"Gestionnaire de clic sur la carte.\"\"\"\n",
|
||||||
|
" if kwargs.get('type') == 'click':\n",
|
||||||
|
" coords = kwargs.get('coordinates')\n",
|
||||||
|
" lat, lon = coords\n",
|
||||||
|
" current_coords['lat'] = lat\n",
|
||||||
|
" current_coords['lon'] = lon\n",
|
||||||
|
" update_classification(lat, lon, k_slider.value)\n",
|
||||||
|
"\n",
|
||||||
|
"def on_k_change(change):\n",
|
||||||
|
" \"\"\"Gestionnaire de changement de k.\"\"\"\n",
|
||||||
|
" if current_coords['lat'] is not None:\n",
|
||||||
|
" update_classification(current_coords['lat'], current_coords['lon'], change['new'])\n",
|
||||||
|
"\n",
|
||||||
|
"# Connecter les événements\n",
|
||||||
|
"m.on_interaction(handle_click)\n",
|
||||||
|
"k_slider.observe(on_k_change, names='value')\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher l'interface\n",
|
||||||
|
"display(VBox([\n",
|
||||||
|
" info_html,\n",
|
||||||
|
" HBox([Label('Nombre de voisins (k):'), k_slider]),\n",
|
||||||
|
" m,\n",
|
||||||
|
" result_output\n",
|
||||||
|
"]))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎯 Points d'intérêt à tester\n",
|
||||||
|
"\n",
|
||||||
|
"Essayez de cliquer sur ces zones :\n",
|
||||||
|
"\n",
|
||||||
|
"- **Ajaccio** : (41.9267, 8.7369) - Capitale 2A\n",
|
||||||
|
"- **Bastia** : (42.7028, 9.4500) - Préfecture 2B\n",
|
||||||
|
"- **Corte** : (42.3062, 9.1509) - Centre de la Corse\n",
|
||||||
|
"- **Frontière approximative** : Zone entre 42.0 et 42.3 latitude\n",
|
||||||
|
"\n",
|
||||||
|
"### Questions à explorer :\n",
|
||||||
|
"1. 🤔 Où se situe la \"frontière\" k-NN entre les deux départements ?\n",
|
||||||
|
"2. 📊 Comment k influence-t-il la classification près de cette frontière ?\n",
|
||||||
|
"3. 🏔️ Y a-t-il des zones ambiguës où le résultat change souvent ?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 💡 Mode manuel (si la carte ne fonctionne pas)\n",
|
||||||
|
"\n",
|
||||||
|
"Si le clic sur carte ne fonctionne pas, utilisez cette cellule :"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Mode manuel : entrez les coordonnées\n",
|
||||||
|
"test_lat = 42.3 # Modifiez ici\n",
|
||||||
|
"test_lon = 9.15 # Modifiez ici\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
"dept_name = 'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"📍 Point : ({test_lat}, {test_lon})\")\n",
|
||||||
|
"print(f\"🎯 Prédiction : {dept_name}\")\n",
|
||||||
|
"print(f\"📊 Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\n🏘️ Les {k} plus proches villages :\")\n",
|
||||||
|
"print(neighbors[['village', 'nom_corse', 'departement', 'distance']].to_string(index=False))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📝 Notes techniques\n",
|
||||||
|
"\n",
|
||||||
|
"Cette version utilise **ipyleaflet** qui offre une vraie interactivité bidirectionnelle entre Python et JavaScript dans Jupyter.\n",
|
||||||
|
"\n",
|
||||||
|
"**Avantages :**\n",
|
||||||
|
"- ✅ Clic directement sur la carte\n",
|
||||||
|
"- ✅ Mise à jour en temps réel\n",
|
||||||
|
"- ✅ Curseur interactif pour k\n",
|
||||||
|
"- ✅ Pas besoin de recharger\n",
|
||||||
|
"\n",
|
||||||
|
"**Prérequis :**\n",
|
||||||
|
"- Jupyter Notebook ou JupyterLab\n",
|
||||||
|
"- Extension widgets activée : `jupyter nbextension enable --py widgetsnbextension`"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
744
activite1/knn_corse_interactive_v2.ipynb
Normal file
744
activite1/knn_corse_interactive_v2.ipynb
Normal file
|
|
@ -0,0 +1,744 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# 🗺️ Classification k-NN : Haute-Corse ou Corse du Sud ?\n",
|
||||||
|
"\n",
|
||||||
|
"## Objectif\n",
|
||||||
|
"Utiliser l'algorithme des **k plus proches voisins (k-NN)** pour déterminer si un point de la carte de Corse se situe en **Haute-Corse (2B)** ou en **Corse du Sud (2A)**, en se basant sur les villages les plus proches.\n",
|
||||||
|
"\n",
|
||||||
|
"## Principe\n",
|
||||||
|
"1. On charge les données des villages corses avec leurs coordonnées GPS et leur département\n",
|
||||||
|
"2. On choisit un point sur la carte\n",
|
||||||
|
"3. On calcule les distances entre ce point et tous les villages\n",
|
||||||
|
"4. On identifie les k villages les plus proches\n",
|
||||||
|
"5. On vote : le département majoritaire parmi ces k villages devient la prédiction"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📦 Installation et imports"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques nécessaires (si besoin)\n",
|
||||||
|
"import sys\n",
|
||||||
|
"!{sys.executable} -m pip install folium pandas numpy -q"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import folium\n",
|
||||||
|
"from folium.plugins import MarkerCluster\n",
|
||||||
|
"import math\n",
|
||||||
|
"import json\n",
|
||||||
|
"from collections import Counter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📊 Chargement des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Charger le fichier CSV\n",
|
||||||
|
"# Remplacez 'villages_corse.csv' par le chemin de votre fichier\n",
|
||||||
|
"df = pd.read_csv('villages_corse.csv', sep='\\t', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher les premières lignes\n",
|
||||||
|
"print(f\"Nombre de villages : {len(df)}\")\n",
|
||||||
|
"print(f\"\\nColonnes : {list(df.columns)}\")\n",
|
||||||
|
"df.head()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🔧 Préparation des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def parse_coordinates(point_geo_str):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Parse la colonne Point_Geo pour extraire latitude et longitude.\n",
|
||||||
|
" Format attendu : \"latitude, longitude\"\n",
|
||||||
|
" Exemple : \"41.984099158, 8.798384636\"\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" try:\n",
|
||||||
|
" # Séparer par la virgule\n",
|
||||||
|
" parts = str(point_geo_str).split(',')\n",
|
||||||
|
" lat = float(parts[0].strip())\n",
|
||||||
|
" lon = float(parts[1].strip())\n",
|
||||||
|
" return lat, lon\n",
|
||||||
|
" except Exception as e:\n",
|
||||||
|
" print(f\"Erreur parsing: {point_geo_str} - {e}\")\n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"# Extraire les coordonnées\n",
|
||||||
|
"df[['latitude', 'longitude']] = df['Point_Geo'].apply(\n",
|
||||||
|
" lambda x: pd.Series(parse_coordinates(x))\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Supprimer les lignes sans coordonnées valides\n",
|
||||||
|
"df = df.dropna(subset=['latitude', 'longitude'])\n",
|
||||||
|
"\n",
|
||||||
|
"# Simplifier les noms de départements\n",
|
||||||
|
"df['dept_simple'] = df['Code Département'].apply(lambda x: '2A' if str(x) == '2A' else '2B')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Villages avec coordonnées valides : {len(df)}\")\n",
|
||||||
|
"print(f\"\\nRépartition par département :\")\n",
|
||||||
|
"print(df['dept_simple'].value_counts())\n",
|
||||||
|
"\n",
|
||||||
|
"df[['Nom français', 'dept_simple', 'latitude', 'longitude']].head(10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📏 Fonction de calcul de distance\n",
|
||||||
|
"\n",
|
||||||
|
"Nous utilisons la **formule de Haversine** pour calculer la distance entre deux points GPS sur la surface de la Terre."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def haversine_distance(lat1, lon1, lat2, lon2):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Calcule la distance en kilomètres entre deux points GPS.\n",
|
||||||
|
" Formule de Haversine.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" R = 6371 # Rayon de la Terre en km\n",
|
||||||
|
" \n",
|
||||||
|
" # Conversion en radians\n",
|
||||||
|
" lat1_rad = math.radians(lat1)\n",
|
||||||
|
" lat2_rad = math.radians(lat2)\n",
|
||||||
|
" delta_lat = math.radians(lat2 - lat1)\n",
|
||||||
|
" delta_lon = math.radians(lon2 - lon1)\n",
|
||||||
|
" \n",
|
||||||
|
" # Formule de Haversine\n",
|
||||||
|
" a = math.sin(delta_lat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(delta_lon/2)**2\n",
|
||||||
|
" c = 2 * math.asin(math.sqrt(a))\n",
|
||||||
|
" \n",
|
||||||
|
" return R * c\n",
|
||||||
|
"\n",
|
||||||
|
"# Test de la fonction\n",
|
||||||
|
"# Distance entre Ajaccio (41.9267, 8.7369) et Bastia (42.7028, 9.4500)\n",
|
||||||
|
"dist_test = haversine_distance(41.9267, 8.7369, 42.7028, 9.4500)\n",
|
||||||
|
"print(f\"Distance Ajaccio-Bastia : {dist_test:.1f} km\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Test avec Afa et Alando (vos exemples)\n",
|
||||||
|
"afa = df[df['Nom français'] == 'Afa'].iloc[0]\n",
|
||||||
|
"alando = df[df['Nom français'] == 'Alando'].iloc[0]\n",
|
||||||
|
"dist_afa_alando = haversine_distance(afa['latitude'], afa['longitude'], \n",
|
||||||
|
" alando['latitude'], alando['longitude'])\n",
|
||||||
|
"print(f\"Distance Afa-Alando : {dist_afa_alando:.1f} km\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎯 Algorithme k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def knn_classify(test_lat, test_lon, df, k=5):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Classifie un point (test_lat, test_lon) en utilisant k-NN.\n",
|
||||||
|
" \n",
|
||||||
|
" Retourne :\n",
|
||||||
|
" - prediction : le département prédit ('2A' ou '2B')\n",
|
||||||
|
" - neighbors : DataFrame des k plus proches voisins\n",
|
||||||
|
" - votes : dictionnaire des votes\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Calculer les distances pour tous les villages\n",
|
||||||
|
" distances = []\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" dist = haversine_distance(test_lat, test_lon, row['latitude'], row['longitude'])\n",
|
||||||
|
" distances.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'nom_corse': row['Nom corse'],\n",
|
||||||
|
" 'departement': row['dept_simple'],\n",
|
||||||
|
" 'latitude': row['latitude'],\n",
|
||||||
|
" 'longitude': row['longitude'],\n",
|
||||||
|
" 'distance': dist\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer un DataFrame et trier par distance\n",
|
||||||
|
" dist_df = pd.DataFrame(distances)\n",
|
||||||
|
" dist_df = dist_df.sort_values('distance')\n",
|
||||||
|
" \n",
|
||||||
|
" # Sélectionner les k plus proches\n",
|
||||||
|
" neighbors = dist_df.head(k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Voter\n",
|
||||||
|
" votes = Counter(neighbors['departement'])\n",
|
||||||
|
" prediction = votes.most_common(1)[0][0]\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction, neighbors, votes\n",
|
||||||
|
"\n",
|
||||||
|
"# Test de l'algorithme avec un point au centre de la Corse\n",
|
||||||
|
"test_lat, test_lon = 42.15, 9.05\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"\\n🎯 Point de test : ({test_lat}, {test_lon})\")\n",
|
||||||
|
"print(f\"\\nAvec k={k} :\")\n",
|
||||||
|
"print(f\"Prédiction : {'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'}\")\n",
|
||||||
|
"print(f\"Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\nLes {k} plus proches voisins :\")\n",
|
||||||
|
"print(neighbors[['village', 'nom_corse', 'departement', 'distance']])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🗺️ Visualisation avec Folium"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def create_map(test_lat=None, test_lon=None, k=5, show_all_villages=False, show_boundaries=False):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Crée une carte interactive avec Folium.\n",
|
||||||
|
" \n",
|
||||||
|
" Paramètres:\n",
|
||||||
|
" - test_lat, test_lon: coordonnées du point à tester\n",
|
||||||
|
" - k: nombre de voisins\n",
|
||||||
|
" - show_all_villages: afficher tous les villages\n",
|
||||||
|
" - show_boundaries: afficher les frontières des communes (peut être lent)\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Centre de la Corse\n",
|
||||||
|
" center_lat = 42.15\n",
|
||||||
|
" center_lon = 9.05\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer la carte\n",
|
||||||
|
" m = folium.Map(\n",
|
||||||
|
" location=[center_lat, center_lon],\n",
|
||||||
|
" zoom_start=9,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les frontières des communes (optionnel)\n",
|
||||||
|
" if show_boundaries:\n",
|
||||||
|
" print(\"Affichage des frontières des communes...\")\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" try:\n",
|
||||||
|
" zone_geo = json.loads(row['Zone_geo'])\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" \n",
|
||||||
|
" folium.GeoJson(\n",
|
||||||
|
" zone_geo,\n",
|
||||||
|
" style_function=lambda x, color=color: {\n",
|
||||||
|
" 'fillColor': color,\n",
|
||||||
|
" 'color': color,\n",
|
||||||
|
" 'weight': 1,\n",
|
||||||
|
" 'fillOpacity': 0.1\n",
|
||||||
|
" },\n",
|
||||||
|
" tooltip=row['Nom français']\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" except:\n",
|
||||||
|
" pass\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher tous les villages (optionnel)\n",
|
||||||
|
" if show_all_villages:\n",
|
||||||
|
" marker_cluster = MarkerCluster().add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['latitude'], row['longitude']],\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color,\n",
|
||||||
|
" fillOpacity=0.4,\n",
|
||||||
|
" popup=f\"<b>{row['Nom français']}</b><br>{row['Nom corse']}<br>({row['dept_simple']})\"\n",
|
||||||
|
" ).add_to(marker_cluster)\n",
|
||||||
|
" \n",
|
||||||
|
" # Si un point de test est fourni\n",
|
||||||
|
" if test_lat is not None and test_lon is not None:\n",
|
||||||
|
" # Classification\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(test_lat, test_lon, df, k=k)\n",
|
||||||
|
" \n",
|
||||||
|
" # Marqueur pour le point de test\n",
|
||||||
|
" color = 'darkred' if prediction == '2A' else 'darkblue'\n",
|
||||||
|
" dept_name = 'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'\n",
|
||||||
|
" \n",
|
||||||
|
" folium.Marker(\n",
|
||||||
|
" location=[test_lat, test_lon],\n",
|
||||||
|
" popup=f\"<b>Point à classifier</b><br>Prédiction : {dept_name}<br>Votes : {dict(votes)}\",\n",
|
||||||
|
" icon=folium.Icon(color=color, icon='star', prefix='fa')\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Afficher les k plus proches voisins\n",
|
||||||
|
" for idx, neighbor in neighbors.iterrows():\n",
|
||||||
|
" # Marqueur pour chaque voisin\n",
|
||||||
|
" color = 'red' if neighbor['departement'] == '2A' else 'blue'\n",
|
||||||
|
" folium.Marker(\n",
|
||||||
|
" location=[neighbor['latitude'], neighbor['longitude']],\n",
|
||||||
|
" popup=f\"<b>{neighbor['village']}</b><br>{neighbor['nom_corse']}<br>{neighbor['departement']}<br>Distance: {neighbor['distance']:.2f} km\",\n",
|
||||||
|
" icon=folium.Icon(color=color, icon='info-sign')\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Ligne entre le point test et le voisin\n",
|
||||||
|
" folium.PolyLine(\n",
|
||||||
|
" locations=[\n",
|
||||||
|
" [test_lat, test_lon],\n",
|
||||||
|
" [neighbor['latitude'], neighbor['longitude']]\n",
|
||||||
|
" ],\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" weight=2,\n",
|
||||||
|
" opacity=0.5,\n",
|
||||||
|
" tooltip=f\"{neighbor['distance']:.2f} km\"\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" # Légende\n",
|
||||||
|
" legend_html = '''\n",
|
||||||
|
" <div style=\"position: fixed; \n",
|
||||||
|
" bottom: 50px; right: 50px; width: 220px; height: 130px; \n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; \n",
|
||||||
|
" font-size:14px; padding: 10px\">\n",
|
||||||
|
" <p><strong>Légende</strong></p>\n",
|
||||||
|
" <p><i class=\"fa fa-circle\" style=\"color:red\"></i> Corse du Sud (2A)</p>\n",
|
||||||
|
" <p><i class=\"fa fa-circle\" style=\"color:blue\"></i> Haute-Corse (2B)</p>\n",
|
||||||
|
" <p><i class=\"fa fa-star\" style=\"color:darkred\"></i> Point à classifier</p>\n",
|
||||||
|
" </div>\n",
|
||||||
|
" '''\n",
|
||||||
|
" m.get_root().html.add_child(folium.Element(legend_html))\n",
|
||||||
|
" \n",
|
||||||
|
" return m\n",
|
||||||
|
"\n",
|
||||||
|
"# Créer la carte avec le point de test\n",
|
||||||
|
"map_with_test = create_map(test_lat=42.15, test_lon=9.05, k=5, show_all_villages=False)\n",
|
||||||
|
"map_with_test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🔬 Expérimentation : Influence de k"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Test avec différentes valeurs de k\n",
|
||||||
|
"test_point = (42.15, 9.05) # Point au centre de la Corse\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Point testé : {test_point}\\n\")\n",
|
||||||
|
"print(f\"{'k':<5} {'Prédiction':<15} {'Votes 2A':<10} {'Votes 2B':<10}\")\n",
|
||||||
|
"print(\"-\" * 50)\n",
|
||||||
|
"\n",
|
||||||
|
"for k in [1, 3, 5, 7, 9, 15, 21]:\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(test_point[0], test_point[1], df, k=k)\n",
|
||||||
|
" votes_2a = votes.get('2A', 0)\n",
|
||||||
|
" votes_2b = votes.get('2B', 0)\n",
|
||||||
|
" dept_name = 'Corse du Sud' if prediction == '2A' else 'Haute-Corse'\n",
|
||||||
|
" print(f\"{k:<5} {dept_name:<15} {votes_2a:<10} {votes_2b:<10}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎮 Mode interactif : Testez vos propres points !\n",
|
||||||
|
"\n",
|
||||||
|
"Modifiez les coordonnées ci-dessous pour tester différents points de la Corse.\n",
|
||||||
|
"\n",
|
||||||
|
"**Quelques repères géographiques :**\n",
|
||||||
|
"- Ajaccio : (41.9267, 8.7369)\n",
|
||||||
|
"- Bastia : (42.7028, 9.4500)\n",
|
||||||
|
"- Corte : (42.3062, 9.1509)\n",
|
||||||
|
"- Porto-Vecchio : (41.5914, 9.2795)\n",
|
||||||
|
"- Calvi : (42.5679, 8.7575)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# === MODIFIEZ CES VALEURS ===\n",
|
||||||
|
"test_latitude = 42.3 # Entre 41.3 (sud) et 43.0 (nord)\n",
|
||||||
|
"test_longitude = 9.15 # Entre 8.5 (ouest) et 9.5 (est)\n",
|
||||||
|
"k_value = 7 # Nombre de voisins\n",
|
||||||
|
"# =============================\n",
|
||||||
|
"\n",
|
||||||
|
"prediction, neighbors, votes = knn_classify(test_latitude, test_longitude, df, k=k_value)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"📍 Point : ({test_latitude}, {test_longitude})\")\n",
|
||||||
|
"print(f\"🔢 k = {k_value}\")\n",
|
||||||
|
"print(f\"\\n🎯 Prédiction : {'Corse du Sud (2A)' if prediction == '2A' else 'Haute-Corse (2B)'}\")\n",
|
||||||
|
"print(f\"\\n📊 Votes : {dict(votes)}\")\n",
|
||||||
|
"print(f\"\\n🏘️ Les {k_value} plus proches villages :\")\n",
|
||||||
|
"print(neighbors[['village', 'nom_corse', 'departement', 'distance']].to_string(index=False))\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher la carte\n",
|
||||||
|
"map_interactive = create_map(test_latitude, test_longitude, k=k_value, show_all_villages=False)\n",
|
||||||
|
"map_interactive"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🌍 Carte complète avec tous les villages"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Afficher tous les villages de Corse\n",
|
||||||
|
"# Note : cette cellule peut prendre quelques secondes à s'exécuter\n",
|
||||||
|
"\n",
|
||||||
|
"map_all = create_map(show_all_villages=True, show_boundaries=False)\n",
|
||||||
|
"map_all"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🗺️ Carte avec frontières des communes (BONUS)\n",
|
||||||
|
"\n",
|
||||||
|
"Cette cellule affiche les frontières réelles des communes. **Attention : cela peut prendre du temps à charger !**"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Carte avec frontières - peut être lent !\n",
|
||||||
|
"# Décommentez la ligne suivante pour l'exécuter\n",
|
||||||
|
"# map_boundaries = create_map(test_lat=42.15, test_lon=9.05, k=5, show_boundaries=True)\n",
|
||||||
|
"# map_boundaries"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 📈 Visualisation de la frontière de décision"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Créer une grille de points et classifier chacun\n",
|
||||||
|
"# Cela permet de visualiser la \"frontière\" selon k-NN\n",
|
||||||
|
"\n",
|
||||||
|
"def create_decision_boundary_map(k=5, grid_resolution=40):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Crée une carte montrant la frontière de décision de k-NN.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Limites de la Corse\n",
|
||||||
|
" lat_min, lat_max = 41.3, 43.0\n",
|
||||||
|
" lon_min, lon_max = 8.5, 9.6\n",
|
||||||
|
" \n",
|
||||||
|
" # Créer une grille\n",
|
||||||
|
" lats = np.linspace(lat_min, lat_max, grid_resolution)\n",
|
||||||
|
" lons = np.linspace(lon_min, lon_max, grid_resolution)\n",
|
||||||
|
" \n",
|
||||||
|
" m = folium.Map(\n",
|
||||||
|
" location=[42.15, 9.05],\n",
|
||||||
|
" zoom_start=8,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" # Classifier chaque point de la grille\n",
|
||||||
|
" print(f\"Classification d'une grille de {grid_resolution}x{grid_resolution} points...\")\n",
|
||||||
|
" total = len(lats) * len(lons)\n",
|
||||||
|
" count = 0\n",
|
||||||
|
" \n",
|
||||||
|
" for lat in lats:\n",
|
||||||
|
" for lon in lons:\n",
|
||||||
|
" prediction, _, _ = knn_classify(lat, lon, df, k=k)\n",
|
||||||
|
" color = '#ffcccc' if prediction == '2A' else '#ccccff'\n",
|
||||||
|
" \n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[lat, lon],\n",
|
||||||
|
" radius=4,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color,\n",
|
||||||
|
" fillOpacity=0.3,\n",
|
||||||
|
" weight=0\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" count += 1\n",
|
||||||
|
" if count % 100 == 0:\n",
|
||||||
|
" print(f\" {count}/{total} points traités ({100*count/total:.1f}%)\")\n",
|
||||||
|
" \n",
|
||||||
|
" print(\"Terminé !\")\n",
|
||||||
|
" \n",
|
||||||
|
" # Ajouter les villages\n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" color = 'red' if row['dept_simple'] == '2A' else 'blue'\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['latitude'], row['longitude']],\n",
|
||||||
|
" radius=2,\n",
|
||||||
|
" color=color,\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color,\n",
|
||||||
|
" fillOpacity=0.8,\n",
|
||||||
|
" popup=row['Nom français']\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
" \n",
|
||||||
|
" return m\n",
|
||||||
|
"\n",
|
||||||
|
"# Créer la carte (réduire grid_resolution si c'est trop lent)\n",
|
||||||
|
"print(f\"Création de la carte de frontière avec k=5...\")\n",
|
||||||
|
"print(\"Note : cela peut prendre 1-2 minutes...\")\n",
|
||||||
|
"boundary_map = create_decision_boundary_map(k=5, grid_resolution=30)\n",
|
||||||
|
"boundary_map"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 💡 Validation de l'algorithme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# BONUS : Validation croisée\n",
|
||||||
|
"# Tester la précision en utilisant les villages eux-mêmes\n",
|
||||||
|
"\n",
|
||||||
|
"def cross_validation(df, k=5, sample_size=100):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Teste la précision de k-NN en utilisant un échantillon de villages.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Prendre un échantillon aléatoire\n",
|
||||||
|
" sample = df.sample(n=min(sample_size, len(df)), random_state=42)\n",
|
||||||
|
" \n",
|
||||||
|
" correct = 0\n",
|
||||||
|
" total = 0\n",
|
||||||
|
" errors = []\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in sample.iterrows():\n",
|
||||||
|
" # Créer un dataset sans ce village\n",
|
||||||
|
" df_without = df.drop(idx)\n",
|
||||||
|
" \n",
|
||||||
|
" # Classifier ce village\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(\n",
|
||||||
|
" row['latitude'], \n",
|
||||||
|
" row['longitude'], \n",
|
||||||
|
" df_without, \n",
|
||||||
|
" k=k\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" if prediction == row['dept_simple']:\n",
|
||||||
|
" correct += 1\n",
|
||||||
|
" else:\n",
|
||||||
|
" errors.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'vrai_dept': row['dept_simple'],\n",
|
||||||
|
" 'prediction': prediction,\n",
|
||||||
|
" 'votes': dict(votes)\n",
|
||||||
|
" })\n",
|
||||||
|
" total += 1\n",
|
||||||
|
" \n",
|
||||||
|
" accuracy = (correct / total) * 100\n",
|
||||||
|
" return accuracy, correct, total, errors\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Test de précision de l'algorithme k-NN...\\n\")\n",
|
||||||
|
"print(\"Validation croisée : chaque village est classifié en fonction de ses voisins.\\n\")\n",
|
||||||
|
"\n",
|
||||||
|
"for k in [1, 3, 5, 10, 15]:\n",
|
||||||
|
" accuracy, correct, total, errors = cross_validation(df, k=k, sample_size=100)\n",
|
||||||
|
" print(f\"k={k:2d} : {accuracy:.1f}% de précision ({correct}/{total} corrects)\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher quelques erreurs pour k=5\n",
|
||||||
|
"print(\"\\n📋 Exemples d'erreurs avec k=5 :\")\n",
|
||||||
|
"_, _, _, errors_k5 = cross_validation(df, k=5, sample_size=100)\n",
|
||||||
|
"if errors_k5:\n",
|
||||||
|
" for error in errors_k5[:5]:\n",
|
||||||
|
" print(f\" • {error['village']} : prédit {error['prediction']} (vrai: {error['vrai_dept']}) - votes: {error['votes']}\")\n",
|
||||||
|
"else:\n",
|
||||||
|
" print(\" Aucune erreur !\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🎓 Questions de réflexion\n",
|
||||||
|
"\n",
|
||||||
|
"1. **Influence de k** : Comment la prédiction change-t-elle avec différentes valeurs de k ?\n",
|
||||||
|
"\n",
|
||||||
|
"2. **Points frontières** : Trouvez des coordonnées où la classification est ambiguë (votes proches).\n",
|
||||||
|
"\n",
|
||||||
|
"3. **Zones problématiques** : Où se situent les villages difficiles à classifier correctement ?\n",
|
||||||
|
"\n",
|
||||||
|
"4. **Validité géographique** : Cette méthode respecte-t-elle toujours les vraies frontières administratives ?\n",
|
||||||
|
"\n",
|
||||||
|
"5. **Améliorations** : Comment pourrait-on améliorer l'algorithme ?\n",
|
||||||
|
" - Pondération par distance inverse\n",
|
||||||
|
" - Prise en compte d'autres critères (altitude, population...)\n",
|
||||||
|
" - k adaptatif selon la densité de villages"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 💡 Exercices supplémentaires\n",
|
||||||
|
"\n",
|
||||||
|
"1. **Trouver la frontière** : Trouvez des points sur la \"frontière\" k-NN (là où un changement de k change la classification)\n",
|
||||||
|
"\n",
|
||||||
|
"2. **Villages isolés** : Identifiez les villages dont le département diffère de leurs k plus proches voisins\n",
|
||||||
|
"\n",
|
||||||
|
"3. **Pondération** : Implémentez une version pondérée où les villages plus proches ont plus d'influence\n",
|
||||||
|
"\n",
|
||||||
|
"4. **Comparaison** : Comparez la frontière k-NN avec la vraie frontière administrative"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# EXERCICE : Villages \"anomaliques\"\n",
|
||||||
|
"# Trouver les villages dont les k plus proches voisins sont majoritairement de l'autre département\n",
|
||||||
|
"\n",
|
||||||
|
"def find_anomalous_villages(df, k=5):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Trouve les villages qui seraient mal classifiés par k-NN.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" anomalies = []\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" # Créer un dataset sans ce village\n",
|
||||||
|
" df_without = df.drop(idx)\n",
|
||||||
|
" \n",
|
||||||
|
" # Classifier ce village\n",
|
||||||
|
" prediction, neighbors, votes = knn_classify(\n",
|
||||||
|
" row['latitude'], \n",
|
||||||
|
" row['longitude'], \n",
|
||||||
|
" df_without, \n",
|
||||||
|
" k=k\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" # Si la prédiction ne correspond pas au vrai département\n",
|
||||||
|
" if prediction != row['dept_simple']:\n",
|
||||||
|
" anomalies.append({\n",
|
||||||
|
" 'village': row['Nom français'],\n",
|
||||||
|
" 'nom_corse': row['Nom corse'],\n",
|
||||||
|
" 'vrai_dept': row['dept_simple'],\n",
|
||||||
|
" 'prediction': prediction,\n",
|
||||||
|
" 'votes_2A': votes.get('2A', 0),\n",
|
||||||
|
" 'votes_2B': votes.get('2B', 0),\n",
|
||||||
|
" 'latitude': row['latitude'],\n",
|
||||||
|
" 'longitude': row['longitude']\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" return pd.DataFrame(anomalies)\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Recherche des villages 'anomaliques' avec k=5...\\n\")\n",
|
||||||
|
"anomalies_df = find_anomalous_villages(df, k=5)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Nombre de villages anomaliques : {len(anomalies_df)}\")\n",
|
||||||
|
"print(f\"\\nVillages qui seraient classifiés dans le mauvais département :\\n\")\n",
|
||||||
|
"print(anomalies_df[['village', 'nom_corse', 'vrai_dept', 'prediction', 'votes_2A', 'votes_2B']])\n",
|
||||||
|
"\n",
|
||||||
|
"# Afficher ces villages sur une carte\n",
|
||||||
|
"if len(anomalies_df) > 0:\n",
|
||||||
|
" m_anomalies = folium.Map(location=[42.15, 9.05], zoom_start=9)\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in anomalies_df.iterrows():\n",
|
||||||
|
" folium.Marker(\n",
|
||||||
|
" location=[row['latitude'], row['longitude']],\n",
|
||||||
|
" popup=f\"<b>{row['village']}</b><br>Vrai: {row['vrai_dept']}<br>Prédit: {row['prediction']}<br>Votes: {row['votes_2A']}-{row['votes_2B']}\",\n",
|
||||||
|
" icon=folium.Icon(color='orange', icon='exclamation-triangle', prefix='fa')\n",
|
||||||
|
" ).add_to(m_anomalies)\n",
|
||||||
|
" \n",
|
||||||
|
" display(m_anomalies)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
631
activite1/knn_interactive_full.html
Normal file
631
activite1/knn_interactive_full.html
Normal file
File diff suppressed because one or more lines are too long
388
activite1/villages_corse.csv
Normal file
388
activite1/villages_corse.csv
Normal file
File diff suppressed because one or more lines are too long
10793
activite2/carte_corse_knn_interactive.html
Normal file
10793
activite2/carte_corse_knn_interactive.html
Normal file
File diff suppressed because one or more lines are too long
688
activite2/classification_corse_knn_V2.ipynb
Normal file
688
activite2/classification_corse_knn_V2.ipynb
Normal file
|
|
@ -0,0 +1,688 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Classification des Micro-régions de Corse par K-NN\n",
|
||||||
|
"\n",
|
||||||
|
"Ce notebook implémente un système de classification des micro-régions corses basé sur l'algorithme des k plus proches voisins (k-NN). Cliquez sur la carte pour identifier la micro-région correspondante.\n",
|
||||||
|
"\n",
|
||||||
|
"**Fichiers nécessaires :**\n",
|
||||||
|
"- `communes-de-corse-en-corse-et-francais.csv` : Liste des communes avec coordonnées GPS\n",
|
||||||
|
"- `communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv` : Territoires de projet par commune"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques nécessaires\n",
|
||||||
|
"!pip install folium pandas numpy scikit-learn --quiet"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import folium\n",
|
||||||
|
"from sklearn.neighbors import KNeighborsClassifier\n",
|
||||||
|
"from IPython.display import display, HTML\n",
|
||||||
|
"import json\n",
|
||||||
|
"import re"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 1. Chargement et préparation des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Chargement du fichier avec les coordonnées GPS\n",
|
||||||
|
"df_coords = pd.read_csv('communes-de-corse-en-corse-et-francais.csv', \n",
|
||||||
|
" sep=';', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Fichier coordonnées: {len(df_coords)} communes\")\n",
|
||||||
|
"print(\"\\nPremières lignes:\")\n",
|
||||||
|
"display(df_coords.head())\n",
|
||||||
|
"print(\"\\nColonnes disponibles:\")\n",
|
||||||
|
"print(df_coords.columns.tolist())"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Chargement du fichier avec les territoires de projet\n",
|
||||||
|
"df_territoires = pd.read_csv('communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv',\n",
|
||||||
|
" sep=';', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Fichier territoires: {len(df_territoires)} communes\")\n",
|
||||||
|
"print(\"\\nPremières lignes:\")\n",
|
||||||
|
"display(df_territoires.head())\n",
|
||||||
|
"print(\"\\nTerritoires de projet (micro-régions):\")\n",
|
||||||
|
"print(sorted(df_territoires['Territoire de projet'].unique()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 2. Extraction des coordonnées GPS"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def extract_coordinates(point_geo_str):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Extrait latitude et longitude de la colonne Point_Geo\n",
|
||||||
|
" Format attendu: \"41.984099158, 8.798384636\"\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" if pd.isna(point_geo_str):\n",
|
||||||
|
" return None, None\n",
|
||||||
|
" \n",
|
||||||
|
" try:\n",
|
||||||
|
" # Supprimer les espaces et split par virgule\n",
|
||||||
|
" coords = str(point_geo_str).strip().split(',')\n",
|
||||||
|
" if len(coords) == 2:\n",
|
||||||
|
" lat = float(coords[0].strip())\n",
|
||||||
|
" lon = float(coords[1].strip())\n",
|
||||||
|
" return lat, lon\n",
|
||||||
|
" except:\n",
|
||||||
|
" pass\n",
|
||||||
|
" \n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"# Extraction des coordonnées\n",
|
||||||
|
"df_coords[['Latitude', 'Longitude']] = df_coords['Point_Geo'].apply(\n",
|
||||||
|
" lambda x: pd.Series(extract_coordinates(x))\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Vérification\n",
|
||||||
|
"print(\"Extraction des coordonnées:\")\n",
|
||||||
|
"print(f\"Communes avec coordonnées: {df_coords['Latitude'].notna().sum()}/{len(df_coords)}\")\n",
|
||||||
|
"print(\"\\nExemple:\")\n",
|
||||||
|
"display(df_coords[['Nom français', 'Latitude', 'Longitude']].head())"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 3. Fusion des deux fichiers"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Normalisation des noms de communes pour la jointure\n",
|
||||||
|
"def normalize_commune_name(name):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Normalise le nom d'une commune pour faciliter la jointure\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" if pd.isna(name):\n",
|
||||||
|
" return ''\n",
|
||||||
|
" # Convertir en majuscules et supprimer les espaces multiples\n",
|
||||||
|
" return str(name).upper().strip()\n",
|
||||||
|
"\n",
|
||||||
|
"df_coords['Commune_norm'] = df_coords['Nom français'].apply(normalize_commune_name)\n",
|
||||||
|
"df_territoires['Commune_norm'] = df_territoires['Commune'].apply(normalize_commune_name)\n",
|
||||||
|
"\n",
|
||||||
|
"# Fusion des deux dataframes\n",
|
||||||
|
"df = pd.merge(\n",
|
||||||
|
" df_coords,\n",
|
||||||
|
" df_territoires[['Commune_norm', 'Territoire de projet']],\n",
|
||||||
|
" on='Commune_norm',\n",
|
||||||
|
" how='inner'\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Renommer pour cohérence\n",
|
||||||
|
"df['Commune'] = df['Nom français']\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Fusion réussie: {len(df)} communes avec coordonnées ET territoire de projet\")\n",
|
||||||
|
"print(\"\\nAperçu des données fusionnées:\")\n",
|
||||||
|
"display(df[['Commune', 'Latitude', 'Longitude', 'Territoire de projet']].head(10))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Nettoyage: supprimer les lignes sans coordonnées\n",
|
||||||
|
"df_clean = df.dropna(subset=['Latitude', 'Longitude', 'Territoire de projet']).copy()\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"\\n✅ Données finales: {len(df_clean)} communes prêtes pour la classification\")\n",
|
||||||
|
"print(f\"\\nRépartition par micro-région:\")\n",
|
||||||
|
"print(df_clean['Territoire de projet'].value_counts().sort_index())"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 4. Entraînement du modèle k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Préparation des données pour k-NN\n",
|
||||||
|
"X = df_clean[['Latitude', 'Longitude']].values\n",
|
||||||
|
"y = df_clean['Territoire de projet'].values\n",
|
||||||
|
"\n",
|
||||||
|
"# Création du modèle k-NN avec k=5 (ajustable)\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"knn = KNeighborsClassifier(n_neighbors=k, weights='distance', metric='haversine')\n",
|
||||||
|
"\n",
|
||||||
|
"# Conversion des coordonnées en radians pour la distance haversine\n",
|
||||||
|
"X_rad = np.radians(X)\n",
|
||||||
|
"\n",
|
||||||
|
"# Entraînement du modèle\n",
|
||||||
|
"knn.fit(X_rad, y)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"✅ Modèle k-NN entraîné avec k={k} voisins\")\n",
|
||||||
|
"print(f\"📊 Nombre de micro-régions: {len(np.unique(y))}\")\n",
|
||||||
|
"print(f\"\\n🗺️ Micro-régions identifiées:\")\n",
|
||||||
|
"for i, region in enumerate(sorted(np.unique(y)), 1):\n",
|
||||||
|
" count = (y == region).sum()\n",
|
||||||
|
" print(f\" {i:2d}. {region} ({count} communes)\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 5. Création de la carte interactive avec Folium"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Couleurs pour chaque micro-région\n",
|
||||||
|
"microregions = sorted(df_clean['Territoire de projet'].unique())\n",
|
||||||
|
"colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', \n",
|
||||||
|
" 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', \n",
|
||||||
|
" 'darkpurple', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']\n",
|
||||||
|
"\n",
|
||||||
|
"color_map = {region: colors[i % len(colors)] for i, region in enumerate(microregions)}\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"🎨 Carte des couleurs par micro-région:\")\n",
|
||||||
|
"for region, color in sorted(color_map.items()):\n",
|
||||||
|
" print(f\" • {region}: {color}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Coordonnées du centre de la Corse\n",
|
||||||
|
"center_lat = df_clean['Latitude'].mean()\n",
|
||||||
|
"center_lon = df_clean['Longitude'].mean()\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Centre de la carte: {center_lat:.4f}°N, {center_lon:.4f}°E\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 6. Carte interactive avec prédiction au clic"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Création de la carte interactive\n",
|
||||||
|
"m_interactive = folium.Map(\n",
|
||||||
|
" location=[center_lat, center_lon],\n",
|
||||||
|
" zoom_start=9,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout des marqueurs pour chaque commune\n",
|
||||||
|
"for idx, row in df_clean.iterrows():\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['Latitude'], row['Longitude']],\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" popup=f\"<b>{row['Commune']}</b><br>{row['Territoire de projet']}<br><small>({row['Latitude']:.4f}, {row['Longitude']:.4f})</small>\",\n",
|
||||||
|
" tooltip=row['Commune'],\n",
|
||||||
|
" color=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fillOpacity=0.7\n",
|
||||||
|
" ).add_to(m_interactive)\n",
|
||||||
|
"\n",
|
||||||
|
"# Préparer les données des communes pour JavaScript\n",
|
||||||
|
"communes_data = df_clean[['Latitude', 'Longitude', 'Commune', 'Territoire de projet']].to_dict('records')\n",
|
||||||
|
"\n",
|
||||||
|
"# JavaScript pour la prédiction k-NN au clic\n",
|
||||||
|
"click_js = f\"\"\"\n",
|
||||||
|
"<script>\n",
|
||||||
|
"// Données des communes\n",
|
||||||
|
"var communesData = {json.dumps(communes_data)};\n",
|
||||||
|
"\n",
|
||||||
|
"// Carte des couleurs\n",
|
||||||
|
"var colorMap = {json.dumps(color_map)};\n",
|
||||||
|
"\n",
|
||||||
|
"// Fonction pour calculer la distance haversine\n",
|
||||||
|
"function haversineDistance(lat1, lon1, lat2, lon2) {{\n",
|
||||||
|
" const R = 6371; // Rayon de la Terre en km\n",
|
||||||
|
" const dLat = (lat2 - lat1) * Math.PI / 180;\n",
|
||||||
|
" const dLon = (lon2 - lon1) * Math.PI / 180;\n",
|
||||||
|
" const a = Math.sin(dLat/2) * Math.sin(dLat/2) +\n",
|
||||||
|
" Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n",
|
||||||
|
" Math.sin(dLon/2) * Math.sin(dLon/2);\n",
|
||||||
|
" const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\n",
|
||||||
|
" return R * c;\n",
|
||||||
|
"}}\n",
|
||||||
|
"\n",
|
||||||
|
"// Fonction k-NN\n",
|
||||||
|
"function predictRegion(lat, lon, k) {{\n",
|
||||||
|
" // Calculer les distances\n",
|
||||||
|
" var distances = communesData.map(function(commune) {{\n",
|
||||||
|
" return {{\n",
|
||||||
|
" distance: haversineDistance(lat, lon, commune.Latitude, commune.Longitude),\n",
|
||||||
|
" region: commune['Territoire de projet'],\n",
|
||||||
|
" commune: commune.Commune\n",
|
||||||
|
" }};\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" // Trier par distance\n",
|
||||||
|
" distances.sort((a, b) => a.distance - b.distance);\n",
|
||||||
|
" \n",
|
||||||
|
" // Prendre les k plus proches\n",
|
||||||
|
" var kNearest = distances.slice(0, k);\n",
|
||||||
|
" \n",
|
||||||
|
" // Vote pondéré par l'inverse de la distance\n",
|
||||||
|
" var votes = {{}};\n",
|
||||||
|
" kNearest.forEach(function(neighbor) {{\n",
|
||||||
|
" var weight = 1 / (neighbor.distance + 0.001); // +0.001 pour éviter division par 0\n",
|
||||||
|
" if (votes[neighbor.region]) {{\n",
|
||||||
|
" votes[neighbor.region] += weight;\n",
|
||||||
|
" }} else {{\n",
|
||||||
|
" votes[neighbor.region] = weight;\n",
|
||||||
|
" }}\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" // Trouver la région gagnante\n",
|
||||||
|
" var maxVote = 0;\n",
|
||||||
|
" var predictedRegion = '';\n",
|
||||||
|
" for (var region in votes) {{\n",
|
||||||
|
" if (votes[region] > maxVote) {{\n",
|
||||||
|
" maxVote = votes[region];\n",
|
||||||
|
" predictedRegion = region;\n",
|
||||||
|
" }}\n",
|
||||||
|
" }}\n",
|
||||||
|
" \n",
|
||||||
|
" return {{\n",
|
||||||
|
" region: predictedRegion,\n",
|
||||||
|
" neighbors: kNearest\n",
|
||||||
|
" }};\n",
|
||||||
|
"}}\n",
|
||||||
|
"\n",
|
||||||
|
"// Variable pour stocker le marqueur de prédiction\n",
|
||||||
|
"var predictionMarker = null;\n",
|
||||||
|
"var neighborLines = [];\n",
|
||||||
|
"\n",
|
||||||
|
"// Attendre que la carte soit chargée\n",
|
||||||
|
"setTimeout(function() {{\n",
|
||||||
|
" var maps = document.querySelectorAll('.folium-map');\n",
|
||||||
|
" if (maps.length > 0) {{\n",
|
||||||
|
" var mapElement = maps[maps.length - 1];\n",
|
||||||
|
" var leafletMap = mapElement._leaflet_map;\n",
|
||||||
|
" \n",
|
||||||
|
" if (leafletMap) {{\n",
|
||||||
|
" leafletMap.on('click', function(e) {{\n",
|
||||||
|
" var lat = e.latlng.lat;\n",
|
||||||
|
" var lon = e.latlng.lng;\n",
|
||||||
|
" \n",
|
||||||
|
" // Prédiction avec k={k}\n",
|
||||||
|
" var result = predictRegion(lat, lon, {k});\n",
|
||||||
|
" \n",
|
||||||
|
" // Supprimer l'ancien marqueur et lignes\n",
|
||||||
|
" if (predictionMarker) {{\n",
|
||||||
|
" leafletMap.removeLayer(predictionMarker);\n",
|
||||||
|
" }}\n",
|
||||||
|
" neighborLines.forEach(function(line) {{\n",
|
||||||
|
" leafletMap.removeLayer(line);\n",
|
||||||
|
" }});\n",
|
||||||
|
" neighborLines = [];\n",
|
||||||
|
" \n",
|
||||||
|
" // Créer le popup avec informations détaillées\n",
|
||||||
|
" var popupContent = '<div style=\"min-width: 200px;\">' +\n",
|
||||||
|
" '<h4 style=\"margin: 5px 0; color: ' + colorMap[result.region] + ';\">🎯 ' + result.region + '</h4>' +\n",
|
||||||
|
" '<p style=\"margin: 5px 0; font-size: 11px;\"><b>Coordonnées cliquées:</b><br>' + \n",
|
||||||
|
" 'Lat: ' + lat.toFixed(5) + '°<br>Lon: ' + lon.toFixed(5) + '°</p>' +\n",
|
||||||
|
" '<hr style=\"margin: 5px 0;\">' +\n",
|
||||||
|
" '<p style=\"margin: 5px 0; font-size: 11px;\"><b>{k} plus proches communes:</b></p>' +\n",
|
||||||
|
" '<ul style=\"margin: 5px 0; padding-left: 20px; font-size: 10px;\">';\n",
|
||||||
|
" \n",
|
||||||
|
" result.neighbors.forEach(function(neighbor, i) {{\n",
|
||||||
|
" popupContent += '<li><b>' + neighbor.commune + '</b> (' + neighbor.distance.toFixed(2) + ' km)</li>';\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" popupContent += '</ul></div>';\n",
|
||||||
|
" \n",
|
||||||
|
" // Ajouter le nouveau marqueur\n",
|
||||||
|
" predictionMarker = L.marker([lat, lon], {{\n",
|
||||||
|
" icon: L.divIcon({{\n",
|
||||||
|
" className: 'prediction-marker',\n",
|
||||||
|
" html: '<div style=\"background-color: ' + colorMap[result.region] + \n",
|
||||||
|
" '; width: 20px; height: 20px; border-radius: 50%; ' +\n",
|
||||||
|
" 'border: 3px solid white; box-shadow: 0 0 10px rgba(0,0,0,0.5);\"></div>',\n",
|
||||||
|
" iconSize: [20, 20]\n",
|
||||||
|
" }})\n",
|
||||||
|
" }}).addTo(leafletMap);\n",
|
||||||
|
" \n",
|
||||||
|
" predictionMarker.bindPopup(popupContent, {{maxWidth: 300}}).openPopup();\n",
|
||||||
|
" \n",
|
||||||
|
" // Ajouter des lignes vers les k plus proches voisins\n",
|
||||||
|
" result.neighbors.forEach(function(neighbor) {{\n",
|
||||||
|
" var commune = communesData.find(c => c.Commune === neighbor.commune);\n",
|
||||||
|
" if (commune) {{\n",
|
||||||
|
" var line = L.polyline(\n",
|
||||||
|
" [[lat, lon], [commune.Latitude, commune.Longitude]],\n",
|
||||||
|
" {{\n",
|
||||||
|
" color: 'gray',\n",
|
||||||
|
" weight: 1,\n",
|
||||||
|
" opacity: 0.5,\n",
|
||||||
|
" dashArray: '5, 5'\n",
|
||||||
|
" }}\n",
|
||||||
|
" ).addTo(leafletMap);\n",
|
||||||
|
" neighborLines.push(line);\n",
|
||||||
|
" }}\n",
|
||||||
|
" }});\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" console.log('✅ Gestionnaire de clic k-NN activé');\n",
|
||||||
|
" console.log('📊 ' + communesData.length + ' communes chargées');\n",
|
||||||
|
" }}\n",
|
||||||
|
" }}\n",
|
||||||
|
"}}, 1000);\n",
|
||||||
|
"</script>\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(click_js))\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout de la légende\n",
|
||||||
|
"legend_html = '''\n",
|
||||||
|
"<div style=\"position: fixed; \n",
|
||||||
|
" top: 10px; right: 10px; width: 250px; max-height: 85vh; overflow-y: auto;\n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; border-radius: 5px;\n",
|
||||||
|
" font-size:12px; padding: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.2);\">\n",
|
||||||
|
"<p style=\"margin-bottom: 8px; font-weight: bold; font-size: 14px;\">🗺️ Micro-régions de Corse</p>\n",
|
||||||
|
"'''\n",
|
||||||
|
"\n",
|
||||||
|
"for region, color in sorted(color_map.items()):\n",
|
||||||
|
" legend_html += f'<p style=\"margin: 3px 0;\"><i class=\"fa fa-circle\" style=\"color:{color}\"></i> {region}</p>'\n",
|
||||||
|
"\n",
|
||||||
|
"legend_html += f'<hr style=\"margin: 8px 0;\"><p style=\"margin: 3px 0; font-size: 11px; color: #666;\">k = {k} voisins<br>Distance: Haversine</p></div>'\n",
|
||||||
|
"\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(legend_html))\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout d'instructions\n",
|
||||||
|
"instructions_html = '''\n",
|
||||||
|
"<div style=\"position: fixed; \n",
|
||||||
|
" bottom: 10px; left: 10px; width: 320px; \n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; border-radius: 5px;\n",
|
||||||
|
" font-size:13px; padding: 12px; box-shadow: 0 0 15px rgba(0,0,0,0.2);\">\n",
|
||||||
|
"<p style=\"margin: 0 0 8px 0; font-weight: bold;\">🖱️ Mode d'emploi</p>\n",
|
||||||
|
"<p style=\"margin: 5px 0; line-height: 1.4;\"><b>Cliquez</b> n'importe où sur la carte pour prédire la micro-région.</p>\n",
|
||||||
|
"<p style=\"margin: 5px 0; line-height: 1.4; font-size: 11px;\">• Un marqueur coloré apparaît au point cliqué<br>\n",
|
||||||
|
"• Les lignes pointillées montrent les k communes les plus proches<br>\n",
|
||||||
|
"• Le popup affiche la prédiction détaillée</p>\n",
|
||||||
|
"</div>\n",
|
||||||
|
"'''\n",
|
||||||
|
"\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(instructions_html))\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"\\n✅ Carte interactive créée avec succès!\")\n",
|
||||||
|
"print(f\"\\n🖱️ Cliquez sur n'importe quel point de la carte pour prédire sa micro-région avec k={k} voisins.\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Affichage de la carte interactive\n",
|
||||||
|
"m_interactive"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 7. Sauvegarde de la carte"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Sauvegarder la carte interactive\n",
|
||||||
|
"m_interactive.save('carte_corse_knn_interactive.html')\n",
|
||||||
|
"print(\"✅ Carte sauvegardée dans 'carte_corse_knn_interactive.html'\")\n",
|
||||||
|
"print(\"📁 Vous pouvez ouvrir ce fichier dans un navigateur pour une utilisation autonome.\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 8. Test de la prédiction (optionnel)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Fonction pour tester la prédiction sur des coordonnées spécifiques\n",
|
||||||
|
"def predict_region(lat, lon, k_value=5):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Prédit la micro-région pour des coordonnées données\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Conversion en radians\n",
|
||||||
|
" coords_rad = np.radians([[lat, lon]])\n",
|
||||||
|
" \n",
|
||||||
|
" # Prédiction\n",
|
||||||
|
" prediction = knn.predict(coords_rad)[0]\n",
|
||||||
|
" \n",
|
||||||
|
" # Trouver les k plus proches voisins\n",
|
||||||
|
" distances, indices = knn.kneighbors(coords_rad)\n",
|
||||||
|
" \n",
|
||||||
|
" # Convertir les distances de radians en km\n",
|
||||||
|
" distances_km = distances[0] * 6371 # Rayon de la Terre en km\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"\\n📍 Coordonnées: {lat:.5f}°N, {lon:.5f}°E\")\n",
|
||||||
|
" print(f\"🎯 Micro-région prédite: {prediction}\")\n",
|
||||||
|
" print(f\"\\n{k_value} plus proches communes:\")\n",
|
||||||
|
" \n",
|
||||||
|
" for i, idx in enumerate(indices[0]):\n",
|
||||||
|
" commune_info = df_clean.iloc[idx]\n",
|
||||||
|
" print(f\" {i+1}. {commune_info['Commune']:30s} ({commune_info['Territoire de projet']:30s}) - {distances_km[i]:6.2f} km\")\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction\n",
|
||||||
|
"\n",
|
||||||
|
"# Exemples de test\n",
|
||||||
|
"print(\"=\" * 100)\n",
|
||||||
|
"print(\"TESTS DE PRÉDICTION k-NN\")\n",
|
||||||
|
"print(\"=\" * 100)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 1: Centre approximatif de la Corse (vers Corte)\n",
|
||||||
|
"print(\"\\n🔍 Test 1: Centre de la Corse\")\n",
|
||||||
|
"predict_region(42.15, 9.15, k)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 2: Nord de la Corse (Balagne/Bastia)\n",
|
||||||
|
"print(\"\\n🔍 Test 2: Nord de la Corse\")\n",
|
||||||
|
"predict_region(42.55, 8.85, k)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 3: Sud de la Corse (vers Porto-Vecchio)\n",
|
||||||
|
"print(\"\\n🔍 Test 3: Sud de la Corse\")\n",
|
||||||
|
"predict_region(41.65, 9.15, k)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 4: Ouest (vers Ajaccio)\n",
|
||||||
|
"print(\"\\n🔍 Test 4: Ouest de la Corse (Ajaccio)\")\n",
|
||||||
|
"predict_region(41.93, 8.74, k)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 9. Analyse de performance (optionnel)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Évaluation de la cohérence du modèle (cross-validation)\n",
|
||||||
|
"from sklearn.model_selection import cross_val_score\n",
|
||||||
|
"\n",
|
||||||
|
"# Test avec différentes valeurs de k\n",
|
||||||
|
"k_values = [3, 5, 7, 9, 11, 15]\n",
|
||||||
|
"scores = []\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"📊 Évaluation de la précision pour différentes valeurs de k:\\n\")\n",
|
||||||
|
"print(f\"{'k':<5} {'Précision moyenne':<20} {'Écart-type':<15}\")\n",
|
||||||
|
"print(\"-\" * 50)\n",
|
||||||
|
"\n",
|
||||||
|
"for k_val in k_values:\n",
|
||||||
|
" knn_temp = KNeighborsClassifier(n_neighbors=k_val, weights='distance', metric='haversine')\n",
|
||||||
|
" cv_scores = cross_val_score(knn_temp, X_rad, y, cv=5)\n",
|
||||||
|
" mean_score = cv_scores.mean()\n",
|
||||||
|
" std_score = cv_scores.std()\n",
|
||||||
|
" scores.append(mean_score)\n",
|
||||||
|
" print(f\"{k_val:<5} {mean_score:.4f} ({mean_score*100:5.2f}%) ± {std_score:.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"best_k = k_values[scores.index(max(scores))]\n",
|
||||||
|
"best_score = max(scores)\n",
|
||||||
|
"print(\"\\n\" + \"=\" * 50)\n",
|
||||||
|
"print(f\"✨ Meilleure valeur de k: {best_k} (précision: {best_score:.4f} / {best_score*100:.2f}%)\")\n",
|
||||||
|
"print(\"=\" * 50)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 10. Statistiques par micro-région"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Statistiques descriptives par micro-région\n",
|
||||||
|
"print(\"📈 STATISTIQUES PAR MICRO-RÉGION\\n\")\n",
|
||||||
|
"print(f\"{'Micro-région':<35} {'Nb communes':<15} {'% du total'}\")\n",
|
||||||
|
"print(\"=\" * 65)\n",
|
||||||
|
"\n",
|
||||||
|
"total_communes = len(df_clean)\n",
|
||||||
|
"stats = df_clean['Territoire de projet'].value_counts().sort_index()\n",
|
||||||
|
"\n",
|
||||||
|
"for region, count in stats.items():\n",
|
||||||
|
" pct = (count / total_communes) * 100\n",
|
||||||
|
" print(f\"{region:<35} {count:<15} {pct:>5.1f}%\")\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"=\" * 65)\n",
|
||||||
|
"print(f\"{'TOTAL':<35} {total_communes:<15} 100.0%\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Conclusion\n",
|
||||||
|
"\n",
|
||||||
|
"✅ **Notebook k-NN Corse - Résumé**\n",
|
||||||
|
"\n",
|
||||||
|
"Ce notebook implémente un classificateur k-NN pour les micro-régions de Corse avec:\n",
|
||||||
|
"1. ✅ Chargement des données depuis 2 fichiers CSV (coordonnées + territoires)\n",
|
||||||
|
"2. ✅ Extraction automatique des coordonnées GPS depuis la colonne Point_Geo\n",
|
||||||
|
"3. ✅ Fusion intelligente des deux sources de données\n",
|
||||||
|
"4. ✅ Entraînement d'un modèle k-NN avec distance haversine\n",
|
||||||
|
"5. ✅ Carte interactive Folium avec prédiction au clic\n",
|
||||||
|
"6. ✅ Visualisation des k plus proches voisins\n",
|
||||||
|
"7. ✅ Tests de performance et validation\n",
|
||||||
|
"8. ✅ Export HTML pour utilisation autonome\n",
|
||||||
|
"\n",
|
||||||
|
"**🖱️ Utilisation:**\n",
|
||||||
|
"- Cliquez n'importe où sur la carte\n",
|
||||||
|
"- Un marqueur coloré apparaît avec la micro-région prédite\n",
|
||||||
|
"- Des lignes pointillées montrent les k communes les plus proches\n",
|
||||||
|
"- Un popup détaille la prédiction et les voisins\n",
|
||||||
|
"\n",
|
||||||
|
"**📁 Fichier exporté:** `carte_corse_knn_interactive.html`\n",
|
||||||
|
"\n",
|
||||||
|
"La carte HTML peut être ouverte dans n'importe quel navigateur pour une utilisation autonome!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
620
activite2/classification_microregions_corse.ipynb
Normal file
620
activite2/classification_microregions_corse.ipynb
Normal file
|
|
@ -0,0 +1,620 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Classification des Micro-régions de Corse par K-NN\n",
|
||||||
|
"\n",
|
||||||
|
"Ce notebook implémente un système de classification des micro-régions corses basé sur l'algorithme des k plus proches voisins (k-NN). Cliquez sur la carte pour identifier la micro-région correspondante."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Installation des bibliothèques nécessaires\n",
|
||||||
|
"!pip install folium pandas numpy scikit-learn geopy --quiet"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import folium\n",
|
||||||
|
"from folium import plugins\n",
|
||||||
|
"from sklearn.neighbors import KNeighborsClassifier\n",
|
||||||
|
"from geopy.geocoders import Nominatim\n",
|
||||||
|
"from geopy.extra.rate_limiter import RateLimiter\n",
|
||||||
|
"import time\n",
|
||||||
|
"from IPython.display import display, HTML\n",
|
||||||
|
"import json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 1. Chargement et préparation des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Chargement du fichier CSV\n",
|
||||||
|
"df = pd.read_csv('communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv', \n",
|
||||||
|
" sep=';', encoding='utf-8')\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Nombre de communes: {len(df)}\")\n",
|
||||||
|
"print(\"\\nPremières lignes:\")\n",
|
||||||
|
"display(df.head())\n",
|
||||||
|
"print(\"\\nTerritoires de projet (micro-régions):\")\n",
|
||||||
|
"print(df['Territoire de projet'].unique())"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 2. Géocodage des communes\n",
|
||||||
|
"\n",
|
||||||
|
"Si le fichier ne contient pas déjà les coordonnées GPS, nous les récupérons via géocodage."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Fonction pour obtenir les coordonnées GPS d'une commune\n",
|
||||||
|
"def geocode_commune(commune, departement, code_postal):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Géocode une commune corse pour obtenir ses coordonnées GPS\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" geolocator = Nominatim(user_agent=\"corse_knn_classifier\")\n",
|
||||||
|
" \n",
|
||||||
|
" try:\n",
|
||||||
|
" # Essai avec le nom de la commune et Corse\n",
|
||||||
|
" query = f\"{commune}, Corse, France\"\n",
|
||||||
|
" location = geolocator.geocode(query, timeout=10)\n",
|
||||||
|
" \n",
|
||||||
|
" if location:\n",
|
||||||
|
" return location.latitude, location.longitude\n",
|
||||||
|
" \n",
|
||||||
|
" # Essai avec le code postal\n",
|
||||||
|
" query = f\"{commune}, {code_postal}, France\"\n",
|
||||||
|
" location = geolocator.geocode(query, timeout=10)\n",
|
||||||
|
" \n",
|
||||||
|
" if location:\n",
|
||||||
|
" return location.latitude, location.longitude\n",
|
||||||
|
" \n",
|
||||||
|
" except Exception as e:\n",
|
||||||
|
" print(f\"Erreur pour {commune}: {e}\")\n",
|
||||||
|
" \n",
|
||||||
|
" return None, None\n",
|
||||||
|
"\n",
|
||||||
|
"# Vérifier si les colonnes GPS existent déjà\n",
|
||||||
|
"if 'Latitude' not in df.columns or 'Longitude' not in df.columns:\n",
|
||||||
|
" print(\"Géocodage des communes en cours... (cela peut prendre quelques minutes)\")\n",
|
||||||
|
" \n",
|
||||||
|
" # Géocodage avec rate limiting pour respecter les limites de l'API\n",
|
||||||
|
" latitudes = []\n",
|
||||||
|
" longitudes = []\n",
|
||||||
|
" \n",
|
||||||
|
" for idx, row in df.iterrows():\n",
|
||||||
|
" lat, lon = geocode_commune(row['Commune'], row['Département'], row['Code Postal'])\n",
|
||||||
|
" latitudes.append(lat)\n",
|
||||||
|
" longitudes.append(lon)\n",
|
||||||
|
" \n",
|
||||||
|
" # Affichage de la progression\n",
|
||||||
|
" if (idx + 1) % 10 == 0:\n",
|
||||||
|
" print(f\"Progression: {idx + 1}/{len(df)} communes géocodées\")\n",
|
||||||
|
" \n",
|
||||||
|
" # Pause pour respecter les limites de l'API\n",
|
||||||
|
" time.sleep(1.5)\n",
|
||||||
|
" \n",
|
||||||
|
" df['Latitude'] = latitudes\n",
|
||||||
|
" df['Longitude'] = longitudes\n",
|
||||||
|
" \n",
|
||||||
|
" # Sauvegarde du dataframe avec coordonnées\n",
|
||||||
|
" df.to_csv('communes_corse_avec_gps.csv', sep=';', index=False, encoding='utf-8')\n",
|
||||||
|
" print(\"\\nGéocodage terminé et sauvegardé dans 'communes_corse_avec_gps.csv'\")\n",
|
||||||
|
"else:\n",
|
||||||
|
" print(\"Les coordonnées GPS sont déjà présentes dans le fichier.\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Supprimer les lignes sans coordonnées\n",
|
||||||
|
"df_clean = df.dropna(subset=['Latitude', 'Longitude']).copy()\n",
|
||||||
|
"print(f\"\\nCommunes avec coordonnées GPS: {len(df_clean)}/{len(df)}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 3. Entraînement du modèle k-NN"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Préparation des données pour k-NN\n",
|
||||||
|
"X = df_clean[['Latitude', 'Longitude']].values\n",
|
||||||
|
"y = df_clean['Territoire de projet'].values\n",
|
||||||
|
"\n",
|
||||||
|
"# Création du modèle k-NN avec k=5 (ajustable)\n",
|
||||||
|
"k = 5\n",
|
||||||
|
"knn = KNeighborsClassifier(n_neighbors=k, weights='distance', metric='haversine')\n",
|
||||||
|
"\n",
|
||||||
|
"# Conversion des coordonnées en radians pour la distance haversine\n",
|
||||||
|
"X_rad = np.radians(X)\n",
|
||||||
|
"\n",
|
||||||
|
"# Entraînement du modèle\n",
|
||||||
|
"knn.fit(X_rad, y)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Modèle k-NN entraîné avec k={k} voisins\")\n",
|
||||||
|
"print(f\"Nombre de micro-régions: {len(np.unique(y))}\")\n",
|
||||||
|
"print(f\"Micro-régions: {sorted(np.unique(y))}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 4. Création de la carte interactive avec Folium"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Couleurs pour chaque micro-région\n",
|
||||||
|
"microregions = sorted(df_clean['Territoire de projet'].unique())\n",
|
||||||
|
"colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', \n",
|
||||||
|
" 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', \n",
|
||||||
|
" 'darkpurple', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']\n",
|
||||||
|
"\n",
|
||||||
|
"color_map = {region: colors[i % len(colors)] for i, region in enumerate(microregions)}\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Carte des couleurs par micro-région:\")\n",
|
||||||
|
"for region, color in color_map.items():\n",
|
||||||
|
" print(f\" {region}: {color}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Coordonnées du centre de la Corse\n",
|
||||||
|
"center_lat = df_clean['Latitude'].mean()\n",
|
||||||
|
"center_lon = df_clean['Longitude'].mean()\n",
|
||||||
|
"\n",
|
||||||
|
"# Création de la carte\n",
|
||||||
|
"m = folium.Map(\n",
|
||||||
|
" location=[center_lat, center_lon],\n",
|
||||||
|
" zoom_start=9,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout des marqueurs pour chaque commune\n",
|
||||||
|
"for idx, row in df_clean.iterrows():\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['Latitude'], row['Longitude']],\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" popup=f\"<b>{row['Commune']}</b><br>{row['Territoire de projet']}\",\n",
|
||||||
|
" tooltip=row['Commune'],\n",
|
||||||
|
" color=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fillOpacity=0.7\n",
|
||||||
|
" ).add_to(m)\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout d'une légende\n",
|
||||||
|
"legend_html = '''\n",
|
||||||
|
"<div style=\"position: fixed; \n",
|
||||||
|
" top: 10px; right: 10px; width: 250px; height: auto; \n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; \n",
|
||||||
|
" font-size:12px; padding: 10px\">\n",
|
||||||
|
"<p style=\"margin-bottom: 5px;\"><b>Micro-régions de Corse</b></p>\n",
|
||||||
|
"'''\n",
|
||||||
|
"\n",
|
||||||
|
"for region, color in sorted(color_map.items()):\n",
|
||||||
|
" legend_html += f'<p style=\"margin: 3px 0;\"><i class=\"fa fa-circle\" style=\"color:{color}\"></i> {region}</p>'\n",
|
||||||
|
"\n",
|
||||||
|
"legend_html += '</div>'\n",
|
||||||
|
"\n",
|
||||||
|
"m.get_root().html.add_child(folium.Element(legend_html))\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout du plugin de clic\n",
|
||||||
|
"# Note: Folium ne supporte pas nativement l'interactivité côté Python en temps réel\n",
|
||||||
|
"# Nous allons créer une version avec JavaScript pour la prédiction\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Carte de base créée avec les communes colorées par micro-région\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 5. Carte interactive avec prédiction au clic\n",
|
||||||
|
"\n",
|
||||||
|
"Cette version utilise JavaScript pour permettre de cliquer sur la carte et afficher la micro-région prédite."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Création d'une nouvelle carte avec interaction JavaScript\n",
|
||||||
|
"m_interactive = folium.Map(\n",
|
||||||
|
" location=[center_lat, center_lon],\n",
|
||||||
|
" zoom_start=9,\n",
|
||||||
|
" tiles='OpenStreetMap'\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout des communes\n",
|
||||||
|
"for idx, row in df_clean.iterrows():\n",
|
||||||
|
" folium.CircleMarker(\n",
|
||||||
|
" location=[row['Latitude'], row['Longitude']],\n",
|
||||||
|
" radius=3,\n",
|
||||||
|
" popup=f\"<b>{row['Commune']}</b><br>{row['Territoire de projet']}\",\n",
|
||||||
|
" tooltip=row['Commune'],\n",
|
||||||
|
" color=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fill=True,\n",
|
||||||
|
" fillColor=color_map[row['Territoire de projet']],\n",
|
||||||
|
" fillOpacity=0.7\n",
|
||||||
|
" ).add_to(m_interactive)\n",
|
||||||
|
"\n",
|
||||||
|
"# Préparer les données des communes pour JavaScript\n",
|
||||||
|
"communes_data = df_clean[['Latitude', 'Longitude', 'Commune', 'Territoire de projet']].to_dict('records')\n",
|
||||||
|
"\n",
|
||||||
|
"# JavaScript pour la prédiction k-NN au clic\n",
|
||||||
|
"click_js = f\"\"\"\n",
|
||||||
|
"<script>\n",
|
||||||
|
"// Données des communes\n",
|
||||||
|
"var communesData = {json.dumps(communes_data)};\n",
|
||||||
|
"\n",
|
||||||
|
"// Carte des couleurs\n",
|
||||||
|
"var colorMap = {json.dumps(color_map)};\n",
|
||||||
|
"\n",
|
||||||
|
"// Fonction pour calculer la distance haversine\n",
|
||||||
|
"function haversineDistance(lat1, lon1, lat2, lon2) {{\n",
|
||||||
|
" const R = 6371; // Rayon de la Terre en km\n",
|
||||||
|
" const dLat = (lat2 - lat1) * Math.PI / 180;\n",
|
||||||
|
" const dLon = (lon2 - lon1) * Math.PI / 180;\n",
|
||||||
|
" const a = Math.sin(dLat/2) * Math.sin(dLat/2) +\n",
|
||||||
|
" Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n",
|
||||||
|
" Math.sin(dLon/2) * Math.sin(dLon/2);\n",
|
||||||
|
" const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\n",
|
||||||
|
" return R * c;\n",
|
||||||
|
"}}\n",
|
||||||
|
"\n",
|
||||||
|
"// Fonction k-NN\n",
|
||||||
|
"function predictRegion(lat, lon, k) {{\n",
|
||||||
|
" // Calculer les distances\n",
|
||||||
|
" var distances = communesData.map(function(commune) {{\n",
|
||||||
|
" return {{\n",
|
||||||
|
" distance: haversineDistance(lat, lon, commune.Latitude, commune.Longitude),\n",
|
||||||
|
" region: commune['Territoire de projet'],\n",
|
||||||
|
" commune: commune.Commune\n",
|
||||||
|
" }};\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" // Trier par distance\n",
|
||||||
|
" distances.sort((a, b) => a.distance - b.distance);\n",
|
||||||
|
" \n",
|
||||||
|
" // Prendre les k plus proches\n",
|
||||||
|
" var kNearest = distances.slice(0, k);\n",
|
||||||
|
" \n",
|
||||||
|
" // Vote pondéré par l'inverse de la distance\n",
|
||||||
|
" var votes = {{}};\n",
|
||||||
|
" kNearest.forEach(function(neighbor) {{\n",
|
||||||
|
" var weight = 1 / (neighbor.distance + 0.001); // +0.001 pour éviter division par 0\n",
|
||||||
|
" if (votes[neighbor.region]) {{\n",
|
||||||
|
" votes[neighbor.region] += weight;\n",
|
||||||
|
" }} else {{\n",
|
||||||
|
" votes[neighbor.region] = weight;\n",
|
||||||
|
" }}\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" // Trouver la région gagnante\n",
|
||||||
|
" var maxVote = 0;\n",
|
||||||
|
" var predictedRegion = '';\n",
|
||||||
|
" for (var region in votes) {{\n",
|
||||||
|
" if (votes[region] > maxVote) {{\n",
|
||||||
|
" maxVote = votes[region];\n",
|
||||||
|
" predictedRegion = region;\n",
|
||||||
|
" }}\n",
|
||||||
|
" }}\n",
|
||||||
|
" \n",
|
||||||
|
" return {{\n",
|
||||||
|
" region: predictedRegion,\n",
|
||||||
|
" neighbors: kNearest\n",
|
||||||
|
" }};\n",
|
||||||
|
"}}\n",
|
||||||
|
"\n",
|
||||||
|
"// Variable pour stocker le marqueur de prédiction\n",
|
||||||
|
"var predictionMarker = null;\n",
|
||||||
|
"var neighborLines = [];\n",
|
||||||
|
"\n",
|
||||||
|
"// Attendre que la carte soit chargée\n",
|
||||||
|
"setTimeout(function() {{\n",
|
||||||
|
" var maps = document.querySelectorAll('.folium-map');\n",
|
||||||
|
" if (maps.length > 0) {{\n",
|
||||||
|
" var mapElement = maps[maps.length - 1];\n",
|
||||||
|
" var leafletMap = mapElement._leaflet_map;\n",
|
||||||
|
" \n",
|
||||||
|
" if (leafletMap) {{\n",
|
||||||
|
" leafletMap.on('click', function(e) {{\n",
|
||||||
|
" var lat = e.latlng.lat;\n",
|
||||||
|
" var lon = e.latlng.lng;\n",
|
||||||
|
" \n",
|
||||||
|
" // Prédiction avec k={k}\n",
|
||||||
|
" var result = predictRegion(lat, lon, {k});\n",
|
||||||
|
" \n",
|
||||||
|
" // Supprimer l'ancien marqueur et lignes\n",
|
||||||
|
" if (predictionMarker) {{\n",
|
||||||
|
" leafletMap.removeLayer(predictionMarker);\n",
|
||||||
|
" }}\n",
|
||||||
|
" neighborLines.forEach(function(line) {{\n",
|
||||||
|
" leafletMap.removeLayer(line);\n",
|
||||||
|
" }});\n",
|
||||||
|
" neighborLines = [];\n",
|
||||||
|
" \n",
|
||||||
|
" // Créer le popup avec informations détaillées\n",
|
||||||
|
" var popupContent = '<div style=\"min-width: 200px;\">' +\n",
|
||||||
|
" '<h4 style=\"margin: 5px 0;\">Prédiction k-NN</h4>' +\n",
|
||||||
|
" '<p style=\"margin: 5px 0;\"><b>Micro-région:</b> ' + result.region + '</p>' +\n",
|
||||||
|
" '<p style=\"margin: 5px 0;\"><b>Coordonnées:</b><br>' + \n",
|
||||||
|
" 'Lat: ' + lat.toFixed(5) + '<br>Lon: ' + lon.toFixed(5) + '</p>' +\n",
|
||||||
|
" '<p style=\"margin: 5px 0;\"><b>{k} plus proches communes:</b></p>' +\n",
|
||||||
|
" '<ul style=\"margin: 5px 0; padding-left: 20px; font-size: 11px;\">';\n",
|
||||||
|
" \n",
|
||||||
|
" result.neighbors.forEach(function(neighbor) {{\n",
|
||||||
|
" popupContent += '<li>' + neighbor.commune + \n",
|
||||||
|
" ' (' + neighbor.distance.toFixed(2) + ' km)</li>';\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" popupContent += '</ul></div>';\n",
|
||||||
|
" \n",
|
||||||
|
" // Ajouter le nouveau marqueur\n",
|
||||||
|
" predictionMarker = L.marker([lat, lon], {{\n",
|
||||||
|
" icon: L.divIcon({{\n",
|
||||||
|
" className: 'prediction-marker',\n",
|
||||||
|
" html: '<div style=\"background-color: ' + colorMap[result.region] + \n",
|
||||||
|
" '; width: 20px; height: 20px; border-radius: 50%; ' +\n",
|
||||||
|
" 'border: 3px solid white; box-shadow: 0 0 10px rgba(0,0,0,0.5);\"></div>',\n",
|
||||||
|
" iconSize: [20, 20]\n",
|
||||||
|
" }})\n",
|
||||||
|
" }}).addTo(leafletMap);\n",
|
||||||
|
" \n",
|
||||||
|
" predictionMarker.bindPopup(popupContent).openPopup();\n",
|
||||||
|
" \n",
|
||||||
|
" // Ajouter des lignes vers les k plus proches voisins\n",
|
||||||
|
" result.neighbors.forEach(function(neighbor) {{\n",
|
||||||
|
" var commune = communesData.find(c => c.Commune === neighbor.commune);\n",
|
||||||
|
" if (commune) {{\n",
|
||||||
|
" var line = L.polyline(\n",
|
||||||
|
" [[lat, lon], [commune.Latitude, commune.Longitude]],\n",
|
||||||
|
" {{\n",
|
||||||
|
" color: 'gray',\n",
|
||||||
|
" weight: 1,\n",
|
||||||
|
" opacity: 0.5,\n",
|
||||||
|
" dashArray: '5, 5'\n",
|
||||||
|
" }}\n",
|
||||||
|
" ).addTo(leafletMap);\n",
|
||||||
|
" neighborLines.push(line);\n",
|
||||||
|
" }}\n",
|
||||||
|
" }});\n",
|
||||||
|
" }});\n",
|
||||||
|
" \n",
|
||||||
|
" console.log('Gestionnaire de clic k-NN activé');\n",
|
||||||
|
" }}\n",
|
||||||
|
" }}\n",
|
||||||
|
"}}, 1000);\n",
|
||||||
|
"</script>\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(click_js))\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout de la légende\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(legend_html))\n",
|
||||||
|
"\n",
|
||||||
|
"# Ajout d'instructions\n",
|
||||||
|
"instructions_html = '''\n",
|
||||||
|
"<div style=\"position: fixed; \n",
|
||||||
|
" bottom: 10px; left: 10px; width: 300px; \n",
|
||||||
|
" background-color: white; border:2px solid grey; z-index:9999; \n",
|
||||||
|
" font-size:13px; padding: 10px\">\n",
|
||||||
|
"<p style=\"margin: 0;\"><b>🖱️ Instructions:</b></p>\n",
|
||||||
|
"<p style=\"margin: 5px 0;\">Cliquez n'importe où sur la carte pour prédire la micro-région à partir de l'algorithme k-NN.</p>\n",
|
||||||
|
"<p style=\"margin: 5px 0;\">Les lignes pointillées montrent les k plus proches communes utilisées pour la prédiction.</p>\n",
|
||||||
|
"</div>\n",
|
||||||
|
"'''\n",
|
||||||
|
"\n",
|
||||||
|
"m_interactive.get_root().html.add_child(folium.Element(instructions_html))\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Carte interactive créée avec succès!\")\n",
|
||||||
|
"print(f\"\\nCliquez sur n'importe quel point de la carte pour prédire sa micro-région avec k={k} voisins.\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Affichage de la carte interactive\n",
|
||||||
|
"m_interactive"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 6. Sauvegarde de la carte"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Sauvegarder la carte interactive\n",
|
||||||
|
"m_interactive.save('carte_corse_knn_interactive.html')\n",
|
||||||
|
"print(\"Carte sauvegardée dans 'carte_corse_knn_interactive.html'\")\n",
|
||||||
|
"print(\"Vous pouvez ouvrir ce fichier dans un navigateur pour une utilisation autonome.\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 7. Test de la prédiction (optionnel)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Fonction pour tester la prédiction sur des coordonnées spécifiques\n",
|
||||||
|
"def predict_region(lat, lon, k_value=5):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Prédit la micro-région pour des coordonnées données\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" # Conversion en radians\n",
|
||||||
|
" coords_rad = np.radians([[lat, lon]])\n",
|
||||||
|
" \n",
|
||||||
|
" # Prédiction\n",
|
||||||
|
" prediction = knn.predict(coords_rad)[0]\n",
|
||||||
|
" \n",
|
||||||
|
" # Trouver les k plus proches voisins\n",
|
||||||
|
" distances, indices = knn.kneighbors(coords_rad)\n",
|
||||||
|
" \n",
|
||||||
|
" # Convertir les distances de radians en km\n",
|
||||||
|
" distances_km = distances[0] * 6371 # Rayon de la Terre en km\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"\\n📍 Coordonnées: {lat:.5f}, {lon:.5f}\")\n",
|
||||||
|
" print(f\"🎯 Micro-région prédite: {prediction}\")\n",
|
||||||
|
" print(f\"\\n{k_value} plus proches communes:\")\n",
|
||||||
|
" \n",
|
||||||
|
" for i, idx in enumerate(indices[0]):\n",
|
||||||
|
" commune_info = df_clean.iloc[idx]\n",
|
||||||
|
" print(f\" {i+1}. {commune_info['Commune']} ({commune_info['Territoire de projet']}) - {distances_km[i]:.2f} km\")\n",
|
||||||
|
" \n",
|
||||||
|
" return prediction\n",
|
||||||
|
"\n",
|
||||||
|
"# Exemples de test\n",
|
||||||
|
"print(\"=\" * 60)\n",
|
||||||
|
"print(\"TESTS DE PRÉDICTION\")\n",
|
||||||
|
"print(\"=\" * 60)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 1: Centre approximatif de la Corse\n",
|
||||||
|
"predict_region(42.15, 9.15, k)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 2: Nord de la Corse (Balagne)\n",
|
||||||
|
"predict_region(42.55, 8.85, k)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 3: Sud de la Corse\n",
|
||||||
|
"predict_region(41.65, 9.15, k)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 8. Analyse de performance (optionnel)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Évaluation de la cohérence du modèle (cross-validation)\n",
|
||||||
|
"from sklearn.model_selection import cross_val_score\n",
|
||||||
|
"\n",
|
||||||
|
"# Test avec différentes valeurs de k\n",
|
||||||
|
"k_values = [3, 5, 7, 9, 11]\n",
|
||||||
|
"scores = []\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Évaluation de la précision pour différentes valeurs de k:\\n\")\n",
|
||||||
|
"\n",
|
||||||
|
"for k_val in k_values:\n",
|
||||||
|
" knn_temp = KNeighborsClassifier(n_neighbors=k_val, weights='distance', metric='haversine')\n",
|
||||||
|
" cv_scores = cross_val_score(knn_temp, X_rad, y, cv=5)\n",
|
||||||
|
" mean_score = cv_scores.mean()\n",
|
||||||
|
" scores.append(mean_score)\n",
|
||||||
|
" print(f\"k={k_val:2d}: Précision moyenne = {mean_score:.3f} (+/- {cv_scores.std():.3f})\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Visualisation simple\n",
|
||||||
|
"print(f\"\\n✨ Meilleure valeur de k: {k_values[scores.index(max(scores))]} (précision: {max(scores):.3f})\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Conclusion\n",
|
||||||
|
"\n",
|
||||||
|
"Ce notebook implémente un classificateur k-NN pour les micro-régions de Corse avec:\n",
|
||||||
|
"- ✅ Chargement et géocodage des communes corses\n",
|
||||||
|
"- ✅ Entraînement d'un modèle k-NN avec distance haversine\n",
|
||||||
|
"- ✅ Carte interactive Folium avec prédiction au clic\n",
|
||||||
|
"- ✅ Visualisation des k plus proches voisins\n",
|
||||||
|
"- ✅ Légende et instructions pour l'utilisateur\n",
|
||||||
|
"\n",
|
||||||
|
"**Utilisation:**\n",
|
||||||
|
"1. Cliquez n'importe où sur la carte\n",
|
||||||
|
"2. Un marqueur coloré apparaît avec la micro-région prédite\n",
|
||||||
|
"3. Des lignes pointillées montrent les k communes les plus proches\n",
|
||||||
|
"4. Un popup détaille la prédiction et les voisins\n",
|
||||||
|
"\n",
|
||||||
|
"La carte HTML peut être ouverte dans n'importe quel navigateur pour une utilisation autonome!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
388
activite2/communes-de-corse-en-corse-et-francais.csv
Normal file
388
activite2/communes-de-corse-en-corse-et-francais.csv
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,361 @@
|
||||||
|
Code Postal;Commune;Canton;Département;Territoire de projet;CODE_REG;INSEE_COM
|
||||||
|
20224;ALBERTACCE;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B007
|
||||||
|
20212;ALZI;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B013
|
||||||
|
20225;AVAPESSA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B025
|
||||||
|
20228;BARRETTALI;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;94;2B030
|
||||||
|
20119;BASTELICA;BASTELICA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A031
|
||||||
|
20200;BASTIA;BASTIA;HAUTE-CORSE;PAYS BASTIAIS;94;2B033
|
||||||
|
20226;BELGODERE;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B034
|
||||||
|
20620;BIGUGLIA;BORGO;HAUTE-CORSE;PAYS BASTIAIS;94;2B037
|
||||||
|
20229;CAMPANA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B052
|
||||||
|
20290;CAMPILE;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;94;2B054
|
||||||
|
20130;CARGESE;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A065
|
||||||
|
20244;CARTICASI;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B068
|
||||||
|
20250;CASANOVA;VENACO;HAUTE-CORSE;CENTRE CORSE;94;2B074
|
||||||
|
20236;CASTIRLA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B083
|
||||||
|
20221;CERVIONE;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B087
|
||||||
|
20256;CORBARA;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B093
|
||||||
|
20167;CUTTOLI-CORTICCHIATO;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A103
|
||||||
|
20212;ERBAJOLO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B105
|
||||||
|
20244;ERONE;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B106
|
||||||
|
20253;FARINOLE;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;94;2B109
|
||||||
|
20245;GALERIA;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;94;2B121
|
||||||
|
20243;ISOLACCIO-DI-FIUMORBO;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B135
|
||||||
|
20244;LAVATOGGIO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B138
|
||||||
|
20224;LOZZI;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B147
|
||||||
|
20260;LUMIO;CALVI;HAUTE-CORSE;PAYS DE BALAGNE;;2B150
|
||||||
|
20112;MELA;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A158
|
||||||
|
20270;MOITA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B161
|
||||||
|
20218;MOLTIFAO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;;2B162
|
||||||
|
20239;MURATO;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B172
|
||||||
|
20225;NESSA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B175
|
||||||
|
20219;NOCETA;VEZZANI;HAUTE-CORSE;CENTRE CORSE;;2B177
|
||||||
|
20234;NOVALE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B179
|
||||||
|
20234;ORTALE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B194
|
||||||
|
20125;ORTO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A196
|
||||||
|
20150;OTA;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A198
|
||||||
|
20167;PERI;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A209
|
||||||
|
20230;PIETRA-DI-VERDE;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B225
|
||||||
|
20234;PIETRICAGGIO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B227
|
||||||
|
20250;POGGIO-DI-VENACO;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B238
|
||||||
|
20237;POGGIO-MARINACCIO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B241
|
||||||
|
20137;PORTO-VECCHIO;PORTO-VECCHIO;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A247
|
||||||
|
20218;PRATO-DI-GIOVELLINA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B248
|
||||||
|
20110;PROPRIANO;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A249
|
||||||
|
20290;PRUNELLI-DI-CASACCONI;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B250
|
||||||
|
20229;RAPAGGIO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B256
|
||||||
|
20217;SAINT-FLORENT;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B298
|
||||||
|
20121;SALICE;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A266
|
||||||
|
20243;SAN-GAVINO-DI-FIUMORBO;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B365
|
||||||
|
20230;SAN-GIOVANNI-DI-MORIANI;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B302
|
||||||
|
20244;SAN-LORENZO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B304
|
||||||
|
20230;SANTA-LUCIA-DI-MORIANI;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B307
|
||||||
|
20221;SANTA-MARIA-POGGIO;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B311
|
||||||
|
20190;SANTA-MARIA-SICHE;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A312
|
||||||
|
20230;TALASANI;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B319
|
||||||
|
20250;TRALONCA;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B329
|
||||||
|
20229;VALLE-D'OREZZA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B338
|
||||||
|
20240;VENTISERI;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B342
|
||||||
|
20110;VIGGIANELLO;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A349
|
||||||
|
20200;VILLE-DI-PIETRABUGNO;SAN-MARTINO-DI-LOTA;HAUTE-CORSE;PAYS BASTIAIS;;2B353
|
||||||
|
20116;ZERUBIA;TALLANO-SCOPAMENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A357
|
||||||
|
20173;ZEVACO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A358
|
||||||
|
20124;ZONZA;LEVIE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A362
|
||||||
|
20244;AITI;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B003
|
||||||
|
20212;ALANDO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B005
|
||||||
|
20167;ALATA;AJACCIO 7E CANTON;CORSE-DU-SUD;PAYS AJACCIEN;94;2A006
|
||||||
|
20251;ALTIANI;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B012
|
||||||
|
20270;ANTISANTI;VEZZANI;HAUTE-CORSE;PLAINE ORIENTALE;94;2B016
|
||||||
|
20167;APPIETTO;AJACCIO 7E CANTON;CORSE-DU-SUD;PAYS AJACCIEN;94;2A017
|
||||||
|
20140;ARGIUSTA-MORICCIO;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A021
|
||||||
|
20151;ARRO;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A022
|
||||||
|
20276;ASCO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B023
|
||||||
|
20121;AZZANA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A027
|
||||||
|
20169;BONIFACIO;BONIFACIO;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A041
|
||||||
|
20290;BORGO;BORGO;HAUTE-CORSE;PAYS BASTIAIS;94;2B042
|
||||||
|
20222;BRANDO;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;94;2B043
|
||||||
|
20212;BUSTANICO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B045
|
||||||
|
20224;CALACUCCIA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B047
|
||||||
|
20111;CALCATOGGIO;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A048
|
||||||
|
20142;CAMPO;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A056
|
||||||
|
20230;CANALE-DI-VERDE;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;94;2B057
|
||||||
|
20217;CANARI;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;94;2B058
|
||||||
|
20229;CARPINETO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B067
|
||||||
|
20111;CASAGLIONE;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A070
|
||||||
|
20225;CATERI;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B084
|
||||||
|
20160;COGGIA;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A090
|
||||||
|
20123;COGNOCOLI-MONTICCHI;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A091
|
||||||
|
20138;COTI-CHIAVARI;SANTA-MARIA-SICHE;CORSE-DU-SUD;PAYS AJACCIEN;94;2A098
|
||||||
|
20148;COZZANO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A099
|
||||||
|
20237;CROCE;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B101
|
||||||
|
20117;ECCICA-SUARELLA;BASTELICA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A104
|
||||||
|
20143;FOZZANO;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A118
|
||||||
|
20600;FURIANI;BASTIA (FURIANI-MONTESORO);HAUTE-CORSE;PAYS BASTIAIS;94;2B120
|
||||||
|
20218;GAVIGNANO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B122
|
||||||
|
20227;GHISONI;GHISONI;HAUTE-CORSE;PLAINE ORIENTALE;94;2B124
|
||||||
|
20100;GRANACE;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A128
|
||||||
|
20153;GUITERA-LES-BAINS;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A133
|
||||||
|
20220;LA PORTA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B246
|
||||||
|
20237;LAMA;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS DE BALAGNE;;2B136
|
||||||
|
20252;LETIA;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A141
|
||||||
|
20165;LORETO-DI-TALLANO;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A146
|
||||||
|
20290;LUCCIANA;BORGO;HAUTE-CORSE;PAYS BASTIAIS;;2B148
|
||||||
|
20228;LURI;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B152
|
||||||
|
20287;MERIA;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B159
|
||||||
|
20140;MOCA-CROCE;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A160
|
||||||
|
20218;MOROSAGLIA;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;;2B169
|
||||||
|
20225;MURO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B173
|
||||||
|
20117;OCANA;BASTELICA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A181
|
||||||
|
20217;OLCANI;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B184
|
||||||
|
20140;OLIVESE;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A186
|
||||||
|
20113;OLMETO;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A189
|
||||||
|
20112;OLMICCIA;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A191
|
||||||
|
20236;OMESSA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B193
|
||||||
|
20147;OSANI;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A197
|
||||||
|
20226;PALASCA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B199
|
||||||
|
20134;PALNECA;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A200
|
||||||
|
20251;PANCHERACCIA;BUSTANICO;HAUTE-CORSE;PLAINE ORIENTALE;;2B201
|
||||||
|
20251;PIEDICORTE-DI-GAGGIO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B218
|
||||||
|
20229;PIEDICROCE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B219
|
||||||
|
20218;PIEDIGRIGGIO;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B220
|
||||||
|
20251;PIETRASERENA;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B226
|
||||||
|
20166;PIETROSELLA;SANTA-MARIA-SICHE;CORSE-DU-SUD;PAYS AJACCIEN;94;2A228
|
||||||
|
20242;PIETROSO;VEZZANI;HAUTE-CORSE;PLAINE ORIENTALE;;2B229
|
||||||
|
20220;PIGNA;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;;2B231
|
||||||
|
20234;PIOBETTA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B234
|
||||||
|
20125;POGGIOLO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A240
|
||||||
|
20246;RAPALE;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B257
|
||||||
|
20247;ROGLIANO;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B261
|
||||||
|
20218;SALICETO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;;2B267
|
||||||
|
20213;SAN-GAVINO-D'AMPUGNANI;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B299
|
||||||
|
20230;SAN-GIULIANO;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B303
|
||||||
|
20200;SANTA-MARIA-DI-LOTA;SAN-MARTINO-DI-LOTA;HAUTE-CORSE;PAYS BASTIAIS;;2B309
|
||||||
|
20212;SANT'ANDREA-DI-BOZIO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B292
|
||||||
|
20151;SANT'ANDREA-D'ORCINO;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A295
|
||||||
|
20230;SANTA-REPARATA-DI-MORIANI;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B317
|
||||||
|
20246;SANTO-PIETRO-DI-TENDA;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B314
|
||||||
|
20145;SARI-SOLENZARA;PORTO-VECCHIO;CORSE-DU-SUD;PLAINE ORIENTALE;94;2A269
|
||||||
|
20140;SERRA-DI-FERRO;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A276
|
||||||
|
20240;SOLARO;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B283
|
||||||
|
20152;SORBOLLANO;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A285
|
||||||
|
20146;SOTTA;FIGARI;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A288
|
||||||
|
20226;SPELONCATO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B290
|
||||||
|
20270;TOX;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B328
|
||||||
|
20234;VALLE-D'ALESANI;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B334
|
||||||
|
20167;VALLE-DI-MEZZANA;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A336
|
||||||
|
20215;VENZOLASCA;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B343
|
||||||
|
20172;VERO;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A345
|
||||||
|
20167;VILLANOVA;AJACCIO 7E CANTON;CORSE-DU-SUD;PAYS AJACCIEN;94;2A351
|
||||||
|
20272;ZALANA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B356
|
||||||
|
20132;ZICAVO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A359
|
||||||
|
20214;ZILIA;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;;2B361
|
||||||
|
20167;AFA;AJACCIO 7E CANTON;CORSE-DU-SUD;PAYS AJACCIEN;94;2A001
|
||||||
|
20270;ALERIA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;94;2B009
|
||||||
|
20220;ALGAJOLA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B010
|
||||||
|
20160;ARBORI;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A019
|
||||||
|
20116;AULLENE;TALLANO-SCOPAMENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A024
|
||||||
|
20190;AZILONE-AMPAZA;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A026
|
||||||
|
20160;BALOGNA;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A028
|
||||||
|
20252;BIGORNO;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;94;2B036
|
||||||
|
20270;CAMPI;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;94;2B053
|
||||||
|
20252;CAMPITELLO;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;94;2B055
|
||||||
|
20170;CARBINI;LEVIE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A061
|
||||||
|
20133;CARBUCCIA;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A062
|
||||||
|
20164;CARGIACA;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A066
|
||||||
|
20237;CASABIANCA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B069
|
||||||
|
20140;CASALABRIVA;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A071
|
||||||
|
20270;CASEVECCHIE;VEZZANI;HAUTE-CORSE;PLAINE ORIENTALE;94;2B075
|
||||||
|
20218;CASTIFAO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B080
|
||||||
|
20238;CENTURI;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;94;2B086
|
||||||
|
20240;CHISA;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;94;2B366
|
||||||
|
20134;CIAMANNACCE;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A089
|
||||||
|
20226;COSTA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B097
|
||||||
|
20126;CRISTINACCE;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A100
|
||||||
|
20275;ERSA;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;94;2B107
|
||||||
|
20126;EVISA;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A108
|
||||||
|
20212;FAVALELLO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B110
|
||||||
|
20225;FELICETO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B112
|
||||||
|
20100;FOCE;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A115
|
||||||
|
20190;FORCIOLO;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A117
|
||||||
|
20240;GHISONACCIA;GHISONI;HAUTE-CORSE;PLAINE ORIENTALE;94;2B123
|
||||||
|
20160;GUAGNO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A131
|
||||||
|
20137;LENTO;ALTO-DI-CASACONI;HAUTE-CORSE;CENTRE CORSE;;2B140
|
||||||
|
20170;L'ILE-ROUSSE;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;;2B134
|
||||||
|
20215;LORETO-DI-CASINCA;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B145
|
||||||
|
20245;MANSO;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;;2B153
|
||||||
|
20141;MARIGNANA;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A154
|
||||||
|
20270;MATRA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B155
|
||||||
|
20259;MAUSOLEO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B156
|
||||||
|
20171;MONACIA-D'AULLENE;FIGARI;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A163
|
||||||
|
20229;MONACIA-D'OREZZA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B164
|
||||||
|
20229;NOCARIO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B176
|
||||||
|
20226;OCCHIATANA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B182
|
||||||
|
20217;OGLIASTRO;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B183
|
||||||
|
20290;ORTIPORIO;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B195
|
||||||
|
20229;PARATA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B202
|
||||||
|
20121;PASTRICCIOLA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A204
|
||||||
|
20272;PIANELLO;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B213
|
||||||
|
20215;PIANO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B214
|
||||||
|
20229;PIE-D'OREZZA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B222
|
||||||
|
20246;PIEVE;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B230
|
||||||
|
20123;PILA-CANALE;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A232
|
||||||
|
20229;POLVEROSO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B243
|
||||||
|
20218;POPOLASCA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B244
|
||||||
|
20215;PORRI;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B245
|
||||||
|
20243;PRUNELLI-DI-FIUMORBO;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B251
|
||||||
|
20122;QUENZA;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A254
|
||||||
|
20237;QUERCITELLO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B255
|
||||||
|
20121;REZZA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A259
|
||||||
|
20244;RUSIO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B264
|
||||||
|
20239;RUTALI;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B265
|
||||||
|
20213;SAN-DAMIANO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B297
|
||||||
|
20170;SAN-GAVINO-DI-CARBINI;LEVIE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A300
|
||||||
|
20230;SAN-NICOLAO;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B313
|
||||||
|
20250;SANTA-LUCIA-DI-MERCURIO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B306
|
||||||
|
20167;SARROLA-CARCOPINO;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A271
|
||||||
|
20243;SERRA-DI-FIUMORBO;PRUNELLI-DI-FIUMORBO;HAUTE-CORSE;PLAINE ORIENTALE;;2B277
|
||||||
|
20147;SERRIERA;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A279
|
||||||
|
20125;SOCCIA;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A282
|
||||||
|
20229;STAZZONA;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B291
|
||||||
|
20270;TALLONE;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B320
|
||||||
|
20234;TARRANO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B321
|
||||||
|
20134;TASSO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A322
|
||||||
|
20259;VALLICA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B339
|
||||||
|
20231;VENACO;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B341
|
||||||
|
20229;VERDESE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B344
|
||||||
|
20290;VOLPAJOLA;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B355
|
||||||
|
20190;ZIGLIARA;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A360
|
||||||
|
20112;ZOZA;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A363
|
||||||
|
20270;AGHIONE;VEZZANI;HAUTE-CORSE;PLAINE ORIENTALE;94;2B002
|
||||||
|
20112;ALTAGENE;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A011
|
||||||
|
20272;AMPRIANI;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;94;2B015
|
||||||
|
20110;ARBELLARA;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A018
|
||||||
|
20129;BASTELICACCIA;AJACCIO 7E CANTON;CORSE-DU-SUD;PAYS AJACCIEN;94;2A032
|
||||||
|
20110;BELVEDERE-CAMPOMORO;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A035
|
||||||
|
20100;BILIA;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A038
|
||||||
|
20228;CAGNANO;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;94;2B046
|
||||||
|
20235;CASTELLO-DI-ROSTINO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B079
|
||||||
|
20218;CASTIGLIONE;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B081
|
||||||
|
20117;CAURO;BASTELICA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A085
|
||||||
|
20230;CHIATRA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;94;2B088
|
||||||
|
20168;CORRANO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A094
|
||||||
|
20250;CORTE;CORTE;HAUTE-CORSE;CENTRE CORSE;94;2B096
|
||||||
|
20290;CROCICCHIA;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;94;2B102
|
||||||
|
20234;FELCE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B111
|
||||||
|
20114;FIGARI;FIGARI;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A114
|
||||||
|
20212;FOCICCHIA;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B116
|
||||||
|
20230;LINGUIZZETTA;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B143
|
||||||
|
20139;LOPIGNA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A144
|
||||||
|
20212;MAZZOLA;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B157
|
||||||
|
20214;MONCALE;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;;2B165
|
||||||
|
20290;MONTE;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B166
|
||||||
|
20214;MONTEGROSSO;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;;2B167
|
||||||
|
20238;MORSIGLIA;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B170
|
||||||
|
20219;MURACCIOLE;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B171
|
||||||
|
20217;NONZA;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B178
|
||||||
|
20226;NOVELLA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B180
|
||||||
|
20232;OLETTA;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B185
|
||||||
|
20232;OLMETA-DI-TUDA;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B188
|
||||||
|
20259;OLMI-CAPPELLA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B190
|
||||||
|
20290;OLMO;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B192
|
||||||
|
20147;PARTINELLO;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A203
|
||||||
|
20290;PENTA-ACQUATELLA;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B206
|
||||||
|
20230;PERO-CASEVECCHIE;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B210
|
||||||
|
20140;PETRETO-BICCHISANO;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A211
|
||||||
|
20131;PIANOTTOLI-CALDARELLO;FIGARI;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A215
|
||||||
|
20234;PIAZZALI;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B216
|
||||||
|
20229;PIEDIPARTINO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B221
|
||||||
|
20218;PIETRALBA;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS DE BALAGNE;;2B223
|
||||||
|
20240;POGGIO-DI-NAZZA;GHISONI;HAUTE-CORSE;PLAINE ORIENTALE;;2B236
|
||||||
|
20213;PRUNO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B252
|
||||||
|
20142;QUASQUARA;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A253
|
||||||
|
20160;RENNO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A258
|
||||||
|
20121;ROSAZIA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A262
|
||||||
|
20112;SAINTE-LUCIE-DE-TALLANO;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A308
|
||||||
|
20134;SAMPOLO;ZICAVO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A268
|
||||||
|
20246;SAN-GAVINO-DI-TENDA;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B301
|
||||||
|
20143;SANTA-MARIA-FIGANIELLA;OLMETO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A310
|
||||||
|
20221;SANT'ANDREA-DI-COTONE;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B293
|
||||||
|
20220;SANT'ANTONINO;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;;2B296
|
||||||
|
20220;SANTA-REPARATA-DI-BALAGNA;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;;2B316
|
||||||
|
20250;SANTO-PIETRO-DI-VENACO;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B315
|
||||||
|
20100;SARTENE;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A272
|
||||||
|
20290;SCOLCA;ALTO-DI-CASACONI;HAUTE-CORSE;PAYS BASTIAIS;;2B274
|
||||||
|
20215;SILVARECCIO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B280
|
||||||
|
20140;SOLLACARO;PETRETO-BICCHISANO;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A284
|
||||||
|
20117;TOLLA;BASTELICA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A326
|
||||||
|
20248;TOMINO;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B327
|
||||||
|
20232;VALLECALLE;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B333
|
||||||
|
20221;VALLE-DI-CAMPOLORO;CAMPOLORO-DI-MORIANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B335
|
||||||
|
20230;VELONE-ORNETO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B340
|
||||||
|
20215;VESCOVATO;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B346
|
||||||
|
20242;VEZZANI;VEZZANI;HAUTE-CORSE;PLAINE ORIENTALE;;2B347
|
||||||
|
20160;VICO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A348
|
||||||
|
20290;VIGNALE;BORGO;HAUTE-CORSE;PAYS BASTIAIS;;2B350
|
||||||
|
20279;VILLE-DI-PARASO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B352
|
||||||
|
20272;ZUANI;MOITA-VERDE;HAUTE-CORSE;PLAINE ORIENTALE;;2B364
|
||||||
|
20000;AJACCIO;AJACCIO;CORSE-DU-SUD;PAYS AJACCIEN;94;2A004
|
||||||
|
20128;ALBITRECCIA;SANTA-MARIA-SICHE;CORSE-DU-SUD;PAYS AJACCIEN;94;2A008
|
||||||
|
20151;AMBIEGNA;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A014
|
||||||
|
20220;AREGNO;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;94;2B020
|
||||||
|
20253;BARBAGGIO;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;94;2B029
|
||||||
|
20235;BISINCHI;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B039
|
||||||
|
20136;BOCOGNANO;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A040
|
||||||
|
20214;CALENZANA;CALENZANA;HAUTE-CORSE;PAYS DE BALAGNE;94;2B049
|
||||||
|
20260;CALVI;CALVI;HAUTE-CORSE;PAYS DE BALAGNE;94;2B050
|
||||||
|
20244;CAMBIA;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B051
|
||||||
|
20235;CANAVAGGIA;ALTO-DI-CASACONI;HAUTE-CORSE;CENTRE CORSE;94;2B059
|
||||||
|
20151;CANNELLE;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A060
|
||||||
|
20229;CARCHETO-BRUSTICO;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B063
|
||||||
|
20190;CARDO-TORGIA;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A064
|
||||||
|
20215;CASALTA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B072
|
||||||
|
20224;CASAMACCIOLI;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B073
|
||||||
|
20213;CASTELLARE-DI-CASINCA;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B077
|
||||||
|
20212;CASTELLARE-DI-MERCURIO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;94;2B078
|
||||||
|
20218;CASTINETA;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;94;2B082
|
||||||
|
20135;CONCA;PORTO-VECCHIO;CORSE-DU-SUD;PLAINE ORIENTALE;94;2A092
|
||||||
|
20224;CORSCIA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;94;2B095
|
||||||
|
20237;FICAJA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B113
|
||||||
|
20157;FRASSETO;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A119
|
||||||
|
20237;GIOCATOJO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;94;2B125
|
||||||
|
20251;GIUNCAGGIO;BUSTANICO;HAUTE-CORSE;PLAINE ORIENTALE;;2B126
|
||||||
|
20100;GIUNCHETO;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A127
|
||||||
|
20100;GROSSA;SARTENE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A129
|
||||||
|
20128;GROSSETO-PRUGNA;SANTA-MARIA-SICHE;CORSE-DU-SUD;PAYS AJACCIEN;94;2A130
|
||||||
|
20128;GUARGUALE;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A132
|
||||||
|
20218;LANO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B137
|
||||||
|
20225;LECCI;PORTO-VECCHIO;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A139
|
||||||
|
20160;LEVIE;LEVIE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A142
|
||||||
|
20240;LUGO-DI-NAZZA;GHISONI;HAUTE-CORSE;PLAINE ORIENTALE;;2B149
|
||||||
|
20220;MONTICELLO;L'ILE-ROUSSE;HAUTE-CORSE;PAYS DE BALAGNE;;2B168
|
||||||
|
20160;MURZO;LES DEUX-SORRU;CORSE-DU-SUD;OUEST CORSE;94;2A174
|
||||||
|
20217;OLMETA-DI-CAPOCORSO;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B187
|
||||||
|
20253;PATRIMONIO;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B205
|
||||||
|
20213;PENTA-DI-CASINCA;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B207
|
||||||
|
20234;PERELLI;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B208
|
||||||
|
20115;PIANA;LES DEUX-SEVI;CORSE-DU-SUD;OUEST CORSE;94;2A212
|
||||||
|
20229;PIAZZOLE;OREZZA-ALESANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B217
|
||||||
|
20233;PIETRACORBARA;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B224
|
||||||
|
20228;PINO;CAPOBIANCO;HAUTE-CORSE;PAYS BASTIAIS;;2B233
|
||||||
|
20259;PIOGGIOLA;BELGODERE;HAUTE-CORSE;PAYS DE BALAGNE;;2B235
|
||||||
|
20232;POGGIO-D'OLETTA;LA CONCA-D'ORO;HAUTE-CORSE;PAYS BASTIAIS;;2B239
|
||||||
|
20230;POGGIO-MEZZANA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B242
|
||||||
|
20250;RIVENTOSA;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B260
|
||||||
|
20219;ROSPIGLIANI;VEZZANI;HAUTE-CORSE;CENTRE CORSE;;2B263
|
||||||
|
20200;SAN-MARTINO-DI-LOTA;SAN-MARTINO-DI-LOTA;HAUTE-CORSE;PAYS BASTIAIS;;2B305
|
||||||
|
20151;SARI-D'ORCINO;CRUZINI-CINARCA;CORSE-DU-SUD;OUEST CORSE;94;2A270
|
||||||
|
20213;SCATA;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B273
|
||||||
|
20212;SERMANO;BUSTANICO;HAUTE-CORSE;CENTRE CORSE;;2B275
|
||||||
|
20127;SERRA-DI-SCOPAMENE;TALLANO-SCOPAMENE;CORSE-DU-SUD;EXTREME SUD / ALTA ROCCA;94;2A278
|
||||||
|
20233;SISCO;SAGRO-DI-SANTA-GIULIA;HAUTE-CORSE;PAYS BASTIAIS;;2B281
|
||||||
|
20213;SORBO-OCAGNANO;VESCOVATO;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B286
|
||||||
|
20246;SORIO;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS BASTIAIS;;2B287
|
||||||
|
20250;SOVERIA;NIOLU-OMESSA;HAUTE-CORSE;CENTRE CORSE;;2B289
|
||||||
|
20230;TAGLIO-ISOLACCIO;FIUMALTO-D'AMPUGNANI;HAUTE-CORSE;CASTAGNICCIA / MARE E MONTI;;2B318
|
||||||
|
20167;TAVACO;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A323
|
||||||
|
20163;TAVERA;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A324
|
||||||
|
20133;UCCIANI;CELAVO-MEZZANA;CORSE-DU-SUD;PAYS AJACCIEN;94;2A330
|
||||||
|
20128;URBALACONE;SANTA-MARIA-SICHE;CORSE-DU-SUD;TARAVO / VALINCO / SARTENAIS;94;2A331
|
||||||
|
20218;URTACA;LE HAUT-NEBBIO;HAUTE-CORSE;PAYS DE BALAGNE;;2B332
|
||||||
|
20235;VALLE-DI-ROSTINO;CASTIFAO-MOROSAGLIA;HAUTE-CORSE;CENTRE CORSE;;2B337
|
||||||
|
20219;VIVARIO;VENACO;HAUTE-CORSE;CENTRE CORSE;;2B354
|
||||||
|
9
activite2/knn_microregions_activite.aux
Normal file
9
activite2/knn_microregions_activite.aux
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
\relax
|
||||||
|
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
||||||
|
\@nameuse{bbl@beforestart}
|
||||||
|
\catcode `:\active
|
||||||
|
\catcode `;\active
|
||||||
|
\catcode `!\active
|
||||||
|
\catcode `?\active
|
||||||
|
\babel@aux{french}{}
|
||||||
|
\gdef \@abspage@last{6}
|
||||||
752
activite2/knn_microregions_activite.log
Normal file
752
activite2/knn_microregions_activite.log
Normal file
|
|
@ -0,0 +1,752 @@
|
||||||
|
This is pdfTeX, Version 3.141592653-2.6-1.40.27 (TeX Live 2026/dev/Arch Linux) (preloaded format=pdflatex 2025.8.2) 23 OCT 2025 13:49
|
||||||
|
entering extended mode
|
||||||
|
restricted \write18 enabled.
|
||||||
|
%&-line parsing enabled.
|
||||||
|
**knn_microregions_activite.tex
|
||||||
|
(./knn_microregions_activite.tex
|
||||||
|
LaTeX2e <2024-11-01> patch level 2
|
||||||
|
L3 programming layer <2025-01-18>
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/article.cls
|
||||||
|
Document Class: article 2024/06/29 v1.4n Standard LaTeX document class
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/size11.clo
|
||||||
|
File: size11.clo 2024/06/29 v1.4n Standard LaTeX file (size option)
|
||||||
|
)
|
||||||
|
\c@part=\count196
|
||||||
|
\c@section=\count197
|
||||||
|
\c@subsection=\count198
|
||||||
|
\c@subsubsection=\count199
|
||||||
|
\c@paragraph=\count266
|
||||||
|
\c@subparagraph=\count267
|
||||||
|
\c@figure=\count268
|
||||||
|
\c@table=\count269
|
||||||
|
\abovecaptionskip=\skip49
|
||||||
|
\belowcaptionskip=\skip50
|
||||||
|
\bibindent=\dimen141
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/inputenc.sty
|
||||||
|
Package: inputenc 2024/02/08 v1.3d Input encoding file
|
||||||
|
\inpenc@prehook=\toks17
|
||||||
|
\inpenc@posthook=\toks18
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/base/fontenc.sty
|
||||||
|
Package: fontenc 2021/04/29 v2.0v Standard LaTeX package
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/babel.sty
|
||||||
|
Package: babel 2025/02/14 v25.4 The multilingual framework for pdfLaTeX, LuaLaT
|
||||||
|
eX and XeLaTeX
|
||||||
|
\babel@savecnt=\count270
|
||||||
|
\U@D=\dimen142
|
||||||
|
\l@unhyphenated=\language5
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/txtbabel.def)
|
||||||
|
\bbl@readstream=\read2
|
||||||
|
\bbl@dirlevel=\count271
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel-french/francais.ldf
|
||||||
|
Language: francais 2024-07-25 v3.6c French support from the babel system
|
||||||
|
|
||||||
|
|
||||||
|
Package francais.ldf Warning: Option `francais' for Babel is *deprecated*,
|
||||||
|
(francais.ldf) it might be removed sooner or later. Please
|
||||||
|
(francais.ldf) use `french' instead; reported on input line 31.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel-french/french.ldf
|
||||||
|
Language: french 2024-07-25 v3.6c French support from the babel system
|
||||||
|
Package babel Info: Hyphen rules for 'acadian' set to \l@french
|
||||||
|
(babel) (\language4). Reported on input line 91.
|
||||||
|
Package babel Info: Hyphen rules for 'canadien' set to \l@french
|
||||||
|
(babel) (\language4). Reported on input line 92.
|
||||||
|
\FB@stdchar=\count272
|
||||||
|
Package babel Info: Making : an active character on input line 421.
|
||||||
|
Package babel Info: Making ; an active character on input line 422.
|
||||||
|
Package babel Info: Making ! an active character on input line 423.
|
||||||
|
Package babel Info: Making ? an active character on input line 424.
|
||||||
|
\FBguill@level=\count273
|
||||||
|
\FBold@everypar=\toks19
|
||||||
|
\FB@Mht=\dimen143
|
||||||
|
\mc@charclass=\count274
|
||||||
|
\mc@charfam=\count275
|
||||||
|
\mc@charslot=\count276
|
||||||
|
\std@mcc=\count277
|
||||||
|
\dec@mcc=\count278
|
||||||
|
\FB@parskip=\dimen144
|
||||||
|
\listindentFB=\dimen145
|
||||||
|
\descindentFB=\dimen146
|
||||||
|
\labelindentFB=\dimen147
|
||||||
|
\labelwidthFB=\dimen148
|
||||||
|
\leftmarginFB=\dimen149
|
||||||
|
\parindentFFN=\dimen150
|
||||||
|
\FBfnindent=\dimen151
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/carlisle/scalefnt.sty)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/geometry/geometry.sty
|
||||||
|
Package: geometry 2020/01/02 v5.9 Page Geometry
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty
|
||||||
|
Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
|
||||||
|
\KV@toks@=\toks20
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/iftex/ifvtex.sty
|
||||||
|
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty
|
||||||
|
Package: iftex 2024/12/12 v1.0g TeX engine tests
|
||||||
|
))
|
||||||
|
\Gm@cnth=\count279
|
||||||
|
\Gm@cntv=\count280
|
||||||
|
\c@Gm@tempcnt=\count281
|
||||||
|
\Gm@bindingoffset=\dimen152
|
||||||
|
\Gm@wd@mp=\dimen153
|
||||||
|
\Gm@odd@mp=\dimen154
|
||||||
|
\Gm@even@mp=\dimen155
|
||||||
|
\Gm@layoutwidth=\dimen156
|
||||||
|
\Gm@layoutheight=\dimen157
|
||||||
|
\Gm@layouthoffset=\dimen158
|
||||||
|
\Gm@layoutvoffset=\dimen159
|
||||||
|
\Gm@dimlist=\toks21
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
|
||||||
|
\pgfutil@everybye=\toks22
|
||||||
|
\pgfutil@tempdima=\dimen160
|
||||||
|
\pgfutil@tempdimb=\dimen161
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
|
||||||
|
\pgfutil@abb=\box52
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/pgf.revision.tex)
|
||||||
|
Package: pgfrcs 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
Package: pgf 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty
|
||||||
|
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty
|
||||||
|
Package: graphics 2024/08/06 v1.4g Standard LaTeX Graphics (DPC,SPQR)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/trig.sty
|
||||||
|
Package: trig 2023/12/02 v1.11 sin cos tan (DPC)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
|
||||||
|
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
|
||||||
|
)
|
||||||
|
Package graphics Info: Driver file: pdftex.def on input line 106.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def
|
||||||
|
File: pdftex.def 2024/04/13 v1.2c Graphics/color driver for pdftex
|
||||||
|
))
|
||||||
|
\Gin@req@height=\dimen162
|
||||||
|
\Gin@req@width=\dimen163
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
|
||||||
|
Package: pgfsys 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
|
||||||
|
\pgfkeys@pathtoks=\toks23
|
||||||
|
\pgfkeys@temptoks=\toks24
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeyslibraryfiltered.code.te
|
||||||
|
x
|
||||||
|
\pgfkeys@tmptoks=\toks25
|
||||||
|
))
|
||||||
|
\pgf@x=\dimen164
|
||||||
|
\pgf@y=\dimen165
|
||||||
|
\pgf@xa=\dimen166
|
||||||
|
\pgf@ya=\dimen167
|
||||||
|
\pgf@xb=\dimen168
|
||||||
|
\pgf@yb=\dimen169
|
||||||
|
\pgf@xc=\dimen170
|
||||||
|
\pgf@yc=\dimen171
|
||||||
|
\pgf@xd=\dimen172
|
||||||
|
\pgf@yd=\dimen173
|
||||||
|
\w@pgf@writea=\write3
|
||||||
|
\r@pgf@reada=\read3
|
||||||
|
\c@pgf@counta=\count282
|
||||||
|
\c@pgf@countb=\count283
|
||||||
|
\c@pgf@countc=\count284
|
||||||
|
\c@pgf@countd=\count285
|
||||||
|
\t@pgf@toka=\toks26
|
||||||
|
\t@pgf@tokb=\toks27
|
||||||
|
\t@pgf@tokc=\toks28
|
||||||
|
\pgf@sys@id@count=\count286
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg
|
||||||
|
File: pgf.cfg 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
Driver file for pgf: pgfsys-pdftex.def
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
|
||||||
|
File: pgfsys-pdftex.def 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def
|
||||||
|
File: pgfsys-common-pdf.def 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex
|
||||||
|
File: pgfsyssoftpath.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfsyssoftpath@smallbuffer@items=\count287
|
||||||
|
\pgfsyssoftpath@bigbuffer@items=\count288
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex
|
||||||
|
File: pgfsysprotocol.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/xcolor/xcolor.sty
|
||||||
|
Package: xcolor 2024/09/29 v3.02 LaTeX color extensions (UK)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics-cfg/color.cfg
|
||||||
|
File: color.cfg 2016/01/02 v1.6 sample color configuration
|
||||||
|
)
|
||||||
|
Package xcolor Info: Driver file: pdftex.def on input line 274.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/graphics/mathcolor.ltx)
|
||||||
|
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1349.
|
||||||
|
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1353.
|
||||||
|
Package xcolor Info: Model `RGB' extended on input line 1365.
|
||||||
|
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1367.
|
||||||
|
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1368.
|
||||||
|
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1369.
|
||||||
|
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1370.
|
||||||
|
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1371.
|
||||||
|
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1372.
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
|
||||||
|
Package: pgfcore 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex
|
||||||
|
\pgfmath@dimen=\dimen174
|
||||||
|
\pgfmath@count=\count289
|
||||||
|
\pgfmath@box=\box53
|
||||||
|
\pgfmath@toks=\toks29
|
||||||
|
\pgfmath@stack@operand=\toks30
|
||||||
|
\pgfmath@stack@operation=\toks31
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code
|
||||||
|
.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.te
|
||||||
|
x) (/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics
|
||||||
|
.code.tex) (/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex
|
||||||
|
\c@pgfmathroundto@lastzeros=\count290
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfint.code.tex)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex
|
||||||
|
File: pgfcorepoints.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@picminx=\dimen175
|
||||||
|
\pgf@picmaxx=\dimen176
|
||||||
|
\pgf@picminy=\dimen177
|
||||||
|
\pgf@picmaxy=\dimen178
|
||||||
|
\pgf@pathminx=\dimen179
|
||||||
|
\pgf@pathmaxx=\dimen180
|
||||||
|
\pgf@pathminy=\dimen181
|
||||||
|
\pgf@pathmaxy=\dimen182
|
||||||
|
\pgf@xx=\dimen183
|
||||||
|
\pgf@xy=\dimen184
|
||||||
|
\pgf@yx=\dimen185
|
||||||
|
\pgf@yy=\dimen186
|
||||||
|
\pgf@zx=\dimen187
|
||||||
|
\pgf@zy=\dimen188
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex
|
||||||
|
File: pgfcorepathconstruct.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@path@lastx=\dimen189
|
||||||
|
\pgf@path@lasty=\dimen190
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex
|
||||||
|
File: pgfcorepathusage.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@shorten@end@additional=\dimen191
|
||||||
|
\pgf@shorten@start@additional=\dimen192
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex
|
||||||
|
File: pgfcorescopes.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfpic=\box54
|
||||||
|
\pgf@hbox=\box55
|
||||||
|
\pgf@layerbox@main=\box56
|
||||||
|
\pgf@picture@serial@count=\count291
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex
|
||||||
|
File: pgfcoregraphicstate.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgflinewidth=\dimen193
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.t
|
||||||
|
ex
|
||||||
|
File: pgfcoretransformations.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@pt@x=\dimen194
|
||||||
|
\pgf@pt@y=\dimen195
|
||||||
|
\pgf@pt@temp=\dimen196
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
|
||||||
|
File: pgfcorequick.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex
|
||||||
|
File: pgfcoreobjects.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.te
|
||||||
|
x
|
||||||
|
File: pgfcorepathprocessing.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex
|
||||||
|
File: pgfcorearrows.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfarrowsep=\dimen197
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
|
||||||
|
File: pgfcoreshade.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@max=\dimen198
|
||||||
|
\pgf@sys@shading@range@num=\count292
|
||||||
|
\pgf@shadingcount=\count293
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex
|
||||||
|
File: pgfcoreimage.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex
|
||||||
|
File: pgfcoreexternal.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfexternal@startupbox=\box57
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex
|
||||||
|
File: pgfcorelayers.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex
|
||||||
|
File: pgfcoretransparency.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex
|
||||||
|
File: pgfcorepatterns.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex
|
||||||
|
File: pgfcorerdf.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
|
||||||
|
File: pgfmoduleshapes.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfnodeparttextbox=\box58
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
|
||||||
|
File: pgfmoduleplot.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty
|
||||||
|
Package: pgfcomp-version-0-65 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@nodesepstart=\dimen199
|
||||||
|
\pgf@nodesepend=\dimen256
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty
|
||||||
|
Package: pgfcomp-version-1-18 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgffor.sty
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/pgf/math/pgfmath.sty
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex
|
||||||
|
Package: pgffor 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgffor@iter=\dimen257
|
||||||
|
\pgffor@skip=\dimen258
|
||||||
|
\pgffor@stack=\toks32
|
||||||
|
\pgffor@toks=\toks33
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex
|
||||||
|
Package: tikz 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.te
|
||||||
|
x
|
||||||
|
File: pgflibraryplothandlers.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgf@plot@mark@count=\count294
|
||||||
|
\pgfplotmarksize=\dimen259
|
||||||
|
)
|
||||||
|
\tikz@lastx=\dimen260
|
||||||
|
\tikz@lasty=\dimen261
|
||||||
|
\tikz@lastxsaved=\dimen262
|
||||||
|
\tikz@lastysaved=\dimen263
|
||||||
|
\tikz@lastmovetox=\dimen264
|
||||||
|
\tikz@lastmovetoy=\dimen265
|
||||||
|
\tikzleveldistance=\dimen266
|
||||||
|
\tikzsiblingdistance=\dimen267
|
||||||
|
\tikz@figbox=\box59
|
||||||
|
\tikz@figbox@bg=\box60
|
||||||
|
\tikz@tempbox=\box61
|
||||||
|
\tikz@tempbox@bg=\box62
|
||||||
|
\tikztreelevel=\count295
|
||||||
|
\tikznumberofchildren=\count296
|
||||||
|
\tikznumberofcurrentchild=\count297
|
||||||
|
\tikz@fig@count=\count298
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex
|
||||||
|
File: pgfmodulematrix.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
\pgfmatrixcurrentrow=\count299
|
||||||
|
\pgfmatrixcurrentcolumn=\count300
|
||||||
|
\pgf@matrix@numberofcolumns=\count301
|
||||||
|
)
|
||||||
|
\tikz@expandcount=\count302
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
topaths.code.tex
|
||||||
|
File: tikzlibrarytopaths.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))) (/usr/share/texmf-dist/tex/latex/amsmath/amsmath.sty
|
||||||
|
Package: amsmath 2024/11/05 v2.17t AMS math features
|
||||||
|
\@mathmargin=\skip51
|
||||||
|
|
||||||
|
For additional information on amsmath, use the `?' option.
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amstext.sty
|
||||||
|
Package: amstext 2021/08/26 v2.01 AMS text
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsgen.sty
|
||||||
|
File: amsgen.sty 1999/11/30 v2.0 generic functions
|
||||||
|
\@emptytoks=\toks34
|
||||||
|
\ex@=\dimen268
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsbsy.sty
|
||||||
|
Package: amsbsy 1999/11/29 v1.2d Bold Symbols
|
||||||
|
\pmbraise@=\dimen269
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsmath/amsopn.sty
|
||||||
|
Package: amsopn 2022/04/08 v2.04 operator names
|
||||||
|
)
|
||||||
|
\inf@bad=\count303
|
||||||
|
LaTeX Info: Redefining \frac on input line 233.
|
||||||
|
\uproot@=\count304
|
||||||
|
\leftroot@=\count305
|
||||||
|
LaTeX Info: Redefining \overline on input line 398.
|
||||||
|
LaTeX Info: Redefining \colon on input line 409.
|
||||||
|
\classnum@=\count306
|
||||||
|
\DOTSCASE@=\count307
|
||||||
|
LaTeX Info: Redefining \ldots on input line 495.
|
||||||
|
LaTeX Info: Redefining \dots on input line 498.
|
||||||
|
LaTeX Info: Redefining \cdots on input line 619.
|
||||||
|
\Mathstrutbox@=\box63
|
||||||
|
\strutbox@=\box64
|
||||||
|
LaTeX Info: Redefining \big on input line 721.
|
||||||
|
LaTeX Info: Redefining \Big on input line 722.
|
||||||
|
LaTeX Info: Redefining \bigg on input line 723.
|
||||||
|
LaTeX Info: Redefining \Bigg on input line 724.
|
||||||
|
\big@size=\dimen270
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OML on input line 742.
|
||||||
|
LaTeX Font Info: Redeclaring font encoding OMS on input line 743.
|
||||||
|
\macc@depth=\count308
|
||||||
|
LaTeX Info: Redefining \bmod on input line 904.
|
||||||
|
LaTeX Info: Redefining \pmod on input line 909.
|
||||||
|
LaTeX Info: Redefining \smash on input line 939.
|
||||||
|
LaTeX Info: Redefining \relbar on input line 969.
|
||||||
|
LaTeX Info: Redefining \Relbar on input line 970.
|
||||||
|
\c@MaxMatrixCols=\count309
|
||||||
|
\dotsspace@=\muskip17
|
||||||
|
\c@parentequation=\count310
|
||||||
|
\dspbrk@lvl=\count311
|
||||||
|
\tag@help=\toks35
|
||||||
|
\row@=\count312
|
||||||
|
\column@=\count313
|
||||||
|
\maxfields@=\count314
|
||||||
|
\andhelp@=\toks36
|
||||||
|
\eqnshift@=\dimen271
|
||||||
|
\alignsep@=\dimen272
|
||||||
|
\tagshift@=\dimen273
|
||||||
|
\tagwidth@=\dimen274
|
||||||
|
\totwidth@=\dimen275
|
||||||
|
\lineht@=\dimen276
|
||||||
|
\@envbody=\toks37
|
||||||
|
\multlinegap=\skip52
|
||||||
|
\multlinetaggap=\skip53
|
||||||
|
\mathdisplay@stack=\toks38
|
||||||
|
LaTeX Info: Redefining \[ on input line 2953.
|
||||||
|
LaTeX Info: Redefining \] on input line 2954.
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/amssymb.sty
|
||||||
|
Package: amssymb 2013/01/14 v3.01 AMS font symbols
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/amsfonts.sty
|
||||||
|
Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
|
||||||
|
\symAMSa=\mathgroup4
|
||||||
|
\symAMSb=\mathgroup5
|
||||||
|
LaTeX Font Info: Redeclaring math symbol \hbar on input line 98.
|
||||||
|
LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
|
||||||
|
(Font) U/euf/m/n --> U/euf/b/n on input line 106.
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/enumitem/enumitem.sty
|
||||||
|
Package: enumitem 2025/02/06 v3.11 Customized lists
|
||||||
|
\labelindent=\skip54
|
||||||
|
\enit@outerparindent=\dimen277
|
||||||
|
\enit@toks=\toks39
|
||||||
|
\enit@inbox=\box65
|
||||||
|
\enit@count@id=\count315
|
||||||
|
\enitdp@description=\count316
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty
|
||||||
|
Package: tcolorbox 2024/10/22 version 6.4.1 text color boxes
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tools/verbatim.sty
|
||||||
|
Package: verbatim 2024-01-22 v1.5x LaTeX2e package for verbatim enhancements
|
||||||
|
\every@verbatim=\toks40
|
||||||
|
\verbatim@line=\toks41
|
||||||
|
\verbatim@in@stream=\read4
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/environ/environ.sty
|
||||||
|
Package: environ 2014/05/04 v0.3 A new way to define environments
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/trimspaces/trimspaces.sty
|
||||||
|
Package: trimspaces 2009/09/17 v1.1 Trim spaces around a token list
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/latex/etoolbox/etoolbox.sty
|
||||||
|
Package: etoolbox 2025/02/11 v2.5l e-TeX tools for LaTeX (JAW)
|
||||||
|
\etb@tempcnta=\count317
|
||||||
|
)
|
||||||
|
\tcb@titlebox=\box66
|
||||||
|
\tcb@upperbox=\box67
|
||||||
|
\tcb@lowerbox=\box68
|
||||||
|
\tcb@phantombox=\box69
|
||||||
|
\c@tcbbreakpart=\count318
|
||||||
|
\c@tcblayer=\count319
|
||||||
|
\c@tcolorbox@number=\count320
|
||||||
|
\l__tcobox_tmpa_box=\box70
|
||||||
|
\l__tcobox_tmpa_dim=\dimen278
|
||||||
|
\tcb@temp=\box71
|
||||||
|
\tcb@temp=\box72
|
||||||
|
\tcb@temp=\box73
|
||||||
|
\tcb@temp=\box74
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty
|
||||||
|
Package: fancyhdr 2025/02/07 v5.2 Extensive control of page headers and footers
|
||||||
|
|
||||||
|
\f@nch@headwidth=\skip55
|
||||||
|
\f@nch@offset@elh=\skip56
|
||||||
|
\f@nch@offset@erh=\skip57
|
||||||
|
\f@nch@offset@olh=\skip58
|
||||||
|
\f@nch@offset@orh=\skip59
|
||||||
|
\f@nch@offset@elf=\skip60
|
||||||
|
\f@nch@offset@erf=\skip61
|
||||||
|
\f@nch@offset@olf=\skip62
|
||||||
|
\f@nch@offset@orf=\skip63
|
||||||
|
\f@nch@height=\skip64
|
||||||
|
\f@nch@footalignment=\skip65
|
||||||
|
\f@nch@widthL=\skip66
|
||||||
|
\f@nch@widthC=\skip67
|
||||||
|
\f@nch@widthR=\skip68
|
||||||
|
\@temptokenb=\toks42
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/latex/tools/multicol.sty
|
||||||
|
Package: multicol 2024/09/14 v1.9i multicolumn formatting (FMi)
|
||||||
|
\c@tracingmulticols=\count321
|
||||||
|
\mult@box=\box75
|
||||||
|
\multicol@leftmargin=\dimen279
|
||||||
|
\c@unbalance=\count322
|
||||||
|
\c@collectmore=\count323
|
||||||
|
\doublecol@number=\count324
|
||||||
|
\multicoltolerance=\count325
|
||||||
|
\multicolpretolerance=\count326
|
||||||
|
\full@width=\dimen280
|
||||||
|
\page@free=\dimen281
|
||||||
|
\premulticols=\dimen282
|
||||||
|
\postmulticols=\dimen283
|
||||||
|
\multicolsep=\skip69
|
||||||
|
\multicolbaselineskip=\skip70
|
||||||
|
\partial@page=\box76
|
||||||
|
\last@line=\box77
|
||||||
|
\mc@boxedresult=\box78
|
||||||
|
\maxbalancingoverflow=\dimen284
|
||||||
|
\mult@rightbox=\box79
|
||||||
|
\mult@grightbox=\box80
|
||||||
|
\mult@firstbox=\box81
|
||||||
|
\mult@gfirstbox=\box82
|
||||||
|
\@tempa=\box83
|
||||||
|
\@tempa=\box84
|
||||||
|
\@tempa=\box85
|
||||||
|
\@tempa=\box86
|
||||||
|
\@tempa=\box87
|
||||||
|
\@tempa=\box88
|
||||||
|
\@tempa=\box89
|
||||||
|
\@tempa=\box90
|
||||||
|
\@tempa=\box91
|
||||||
|
\@tempa=\box92
|
||||||
|
\@tempa=\box93
|
||||||
|
\@tempa=\box94
|
||||||
|
\@tempa=\box95
|
||||||
|
\@tempa=\box96
|
||||||
|
\@tempa=\box97
|
||||||
|
\@tempa=\box98
|
||||||
|
\@tempa=\box99
|
||||||
|
\@tempa=\box100
|
||||||
|
\@tempa=\box101
|
||||||
|
\@tempa=\box102
|
||||||
|
\@tempa=\box103
|
||||||
|
\@tempa=\box104
|
||||||
|
\@tempa=\box105
|
||||||
|
\@tempa=\box106
|
||||||
|
\@tempa=\box107
|
||||||
|
\@tempa=\box108
|
||||||
|
\@tempa=\box109
|
||||||
|
\@tempa=\box110
|
||||||
|
\@tempa=\box111
|
||||||
|
\@tempa=\box112
|
||||||
|
\@tempa=\box113
|
||||||
|
\@tempa=\box114
|
||||||
|
\@tempa=\box115
|
||||||
|
\@tempa=\box116
|
||||||
|
\@tempa=\box117
|
||||||
|
\@tempa=\box118
|
||||||
|
\c@minrows=\count327
|
||||||
|
\c@columnbadness=\count328
|
||||||
|
\c@finalcolumnbadness=\count329
|
||||||
|
\last@try=\dimen285
|
||||||
|
\multicolovershoot=\dimen286
|
||||||
|
\multicolundershoot=\dimen287
|
||||||
|
\mult@nat@firstbox=\box119
|
||||||
|
\colbreak@box=\box120
|
||||||
|
\mc@col@check@num=\count330
|
||||||
|
)
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
shapes.geometric.code.tex
|
||||||
|
File: tikzlibraryshapes.geometric.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.geomet
|
||||||
|
ric.code.tex
|
||||||
|
File: pgflibraryshapes.geometric.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
))
|
||||||
|
(/usr/share/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrary
|
||||||
|
calc.code.tex
|
||||||
|
File: tikzlibrarycalc.code.tex 2023-01-15 v3.1.10 (3.1.10)
|
||||||
|
) (/usr/share/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
|
||||||
|
File: l3backend-pdftex.def 2024-05-08 L3 backend support: PDF output (pdfTeX)
|
||||||
|
\l__color_backend_stack_int=\count331
|
||||||
|
\l__pdf_internal_box=\box121
|
||||||
|
) (./knn_microregions_activite.aux
|
||||||
|
(/usr/share/texmf-dist/tex/generic/babel/locale/fr/babel-french.tex
|
||||||
|
Package babel Info: Importing font and identification data for french
|
||||||
|
(babel) from babel-fr.ini. Reported on input line 11.
|
||||||
|
))
|
||||||
|
\openout1 = `knn_microregions_activite.aux'.
|
||||||
|
|
||||||
|
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 36.
|
||||||
|
LaTeX Font Info: ... okay on input line 36.
|
||||||
|
LaTeX Info: Redefining \degres on input line 36.
|
||||||
|
Package french.ldf Info: Setting StandardItemizeEnv=true for
|
||||||
|
(french.ldf) compatibility with enumitem package,
|
||||||
|
(french.ldf) reported on input line 36.
|
||||||
|
Package french.ldf Info: Setting StandardEnumerateEnv=true for
|
||||||
|
(french.ldf) compatibility with enumitem package,
|
||||||
|
(french.ldf) reported on input line 36.
|
||||||
|
LaTeX Info: Redefining \up on input line 36.
|
||||||
|
|
||||||
|
*geometry* driver: auto-detecting
|
||||||
|
*geometry* detected driver: pdftex
|
||||||
|
*geometry* verbose mode - [ preamble ] result:
|
||||||
|
* driver: pdftex
|
||||||
|
* paper: a4paper
|
||||||
|
* layout: <same size as paper>
|
||||||
|
* layoutoffset:(h,v)=(0.0pt,0.0pt)
|
||||||
|
* modes:
|
||||||
|
* h-part:(L,W,R)=(56.9055pt, 483.69687pt, 56.9055pt)
|
||||||
|
* v-part:(T,H,B)=(56.9055pt, 731.23584pt, 56.9055pt)
|
||||||
|
* \paperwidth=597.50787pt
|
||||||
|
* \paperheight=845.04684pt
|
||||||
|
* \textwidth=483.69687pt
|
||||||
|
* \textheight=731.23584pt
|
||||||
|
* \oddsidemargin=-15.36449pt
|
||||||
|
* \evensidemargin=-15.36449pt
|
||||||
|
* \topmargin=-52.36449pt
|
||||||
|
* \headheight=12.0pt
|
||||||
|
* \headsep=25.0pt
|
||||||
|
* \topskip=11.0pt
|
||||||
|
* \footskip=30.0pt
|
||||||
|
* \marginparwidth=50.0pt
|
||||||
|
* \marginparsep=10.0pt
|
||||||
|
* \columnsep=10.0pt
|
||||||
|
* \skip\footins=10.0pt plus 4.0pt minus 2.0pt
|
||||||
|
* \hoffset=0.0pt
|
||||||
|
* \voffset=0.0pt
|
||||||
|
* \mag=1000
|
||||||
|
* \@twocolumnfalse
|
||||||
|
* \@twosidefalse
|
||||||
|
* \@mparswitchfalse
|
||||||
|
* \@reversemarginfalse
|
||||||
|
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
|
||||||
|
[Loading MPS to PDF converter (version 2006.09.02).]
|
||||||
|
\scratchcounter=\count332
|
||||||
|
\scratchdimen=\dimen288
|
||||||
|
\scratchbox=\box122
|
||||||
|
\nofMPsegments=\count333
|
||||||
|
\nofMParguments=\count334
|
||||||
|
\everyMPshowfont=\toks43
|
||||||
|
\MPscratchCnt=\count335
|
||||||
|
\MPscratchDim=\dimen289
|
||||||
|
\MPnumerator=\count336
|
||||||
|
\makeMPintoPDFobject=\count337
|
||||||
|
\everyMPtoPDFconversion=\toks44
|
||||||
|
) (/usr/share/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
|
||||||
|
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
|
||||||
|
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
|
||||||
|
85.
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
|
||||||
|
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
|
||||||
|
e
|
||||||
|
))
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msa on input line 63.
|
||||||
|
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/umsa.fd
|
||||||
|
File: umsa.fd 2013/01/14 v3.01 AMS symbols A
|
||||||
|
)
|
||||||
|
LaTeX Font Info: Trying to load font information for U+msb on input line 63.
|
||||||
|
|
||||||
|
|
||||||
|
(/usr/share/texmf-dist/tex/latex/amsfonts/umsb.fd
|
||||||
|
File: umsb.fd 2013/01/14 v3.01 AMS symbols B
|
||||||
|
)
|
||||||
|
|
||||||
|
[1
|
||||||
|
|
||||||
|
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}{/usr/share/texmf-dist/fonts
|
||||||
|
/enc/dvips/cm-super/cm-super-t1.enc}]
|
||||||
|
|
||||||
|
[2]
|
||||||
|
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[4]
|
||||||
|
|
||||||
|
[5]
|
||||||
|
|
||||||
|
[6] (./knn_microregions_activite.aux)
|
||||||
|
***********
|
||||||
|
LaTeX2e <2024-11-01> patch level 2
|
||||||
|
L3 programming layer <2025-01-18>
|
||||||
|
***********
|
||||||
|
)
|
||||||
|
Here is how much of TeX's memory you used:
|
||||||
|
19631 strings out of 475142
|
||||||
|
396220 string characters out of 5765947
|
||||||
|
785977 words of memory out of 5000000
|
||||||
|
42341 multiletter control sequences out of 15000+600000
|
||||||
|
571118 words of font info for 64 fonts, out of 8000000 for 9000
|
||||||
|
14 hyphenation exceptions out of 8191
|
||||||
|
102i,11n,107p,426b,737s stack positions out of 10000i,1000n,20000p,200000b,200000s
|
||||||
|
</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/
|
||||||
|
texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/share/texmf-dist/fon
|
||||||
|
ts/type1/public/cm-super/sfbx1095.pfb></usr/share/texmf-dist/fonts/type1/public
|
||||||
|
/cm-super/sfbx1200.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfbx1
|
||||||
|
440.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfbx2488.pfb></usr/s
|
||||||
|
hare/texmf-dist/fonts/type1/public/cm-super/sfrm1000.pfb></usr/share/texmf-dist
|
||||||
|
/fonts/type1/public/cm-super/sfrm1095.pfb></usr/share/texmf-dist/fonts/type1/pu
|
||||||
|
blic/cm-super/sfti1095.pfb>
|
||||||
|
Output written on knn_microregions_activite.pdf (6 pages, 170496 bytes).
|
||||||
|
PDF statistics:
|
||||||
|
72 PDF objects out of 1000 (max. 8388607)
|
||||||
|
45 compressed objects within 1 object stream
|
||||||
|
0 named destinations out of 1000 (max. 500000)
|
||||||
|
13 words of extra memory for PDF output out of 10000 (max. 10000000)
|
||||||
|
|
||||||
BIN
activite2/knn_microregions_activite.pdf
Normal file
BIN
activite2/knn_microregions_activite.pdf
Normal file
Binary file not shown.
BIN
activite2/knn_microregions_activite.synctex.gz
Normal file
BIN
activite2/knn_microregions_activite.synctex.gz
Normal file
Binary file not shown.
403
activite2/knn_microregions_activite.tex
Normal file
403
activite2/knn_microregions_activite.tex
Normal file
|
|
@ -0,0 +1,403 @@
|
||||||
|
\documentclass[a4paper,11pt]{article}
|
||||||
|
|
||||||
|
% Packages
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[francais]{babel}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{enumitem}
|
||||||
|
\usepackage{xcolor}
|
||||||
|
\usepackage{tcolorbox}
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\usepackage{multicol}
|
||||||
|
|
||||||
|
% Configuration de la page
|
||||||
|
\geometry{margin=2cm}
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[C]{Page \thepage/4 -- Activité k-NN : Micro-régions}
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
|
||||||
|
% Couleurs pour les micro-régions
|
||||||
|
\definecolor{region1}{RGB}{231,76,60} % Rouge
|
||||||
|
\definecolor{region2}{RGB}{52,152,219} % Bleu
|
||||||
|
\definecolor{region3}{RGB}{46,204,113} % Vert
|
||||||
|
\definecolor{region4}{RGB}{241,196,15} % Jaune
|
||||||
|
\definecolor{region5}{RGB}{155,89,182} % Violet
|
||||||
|
\definecolor{lightblue}{RGB}{227,242,253}
|
||||||
|
\definecolor{lightyellow}{RGB}{255,243,205}
|
||||||
|
|
||||||
|
% Configuration TikZ
|
||||||
|
\usetikzlibrary{shapes.geometric,calc}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% ============= PAGE 1 =============
|
||||||
|
\begin{center}
|
||||||
|
{\Huge \textbf{Activité débranchée : k-NN}}\\[0.3cm]
|
||||||
|
{\Large \textbf{Classification par micro-régions}}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{Objectif :} Utiliser l'algorithme k-NN pour déterminer à quelle micro-région appartient un nouveau point, en se basant sur ses plus proches voisins.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightblue,colframe=blue!75!black,title=\textbf{Principe}]
|
||||||
|
\begin{itemize}[leftmargin=*]
|
||||||
|
\item On dispose de points classifiés en plusieurs \textit{zones} (micro-régions)
|
||||||
|
\item Pour classifier un nouveau point, on identifie ses \textit{k} plus proches voisins
|
||||||
|
\item La zone majoritaire parmi ces \textit{k} voisins devient la classification du point
|
||||||
|
\item \textbf{Différence avec 2 classes :} Avec plusieurs zones, les votes sont plus complexes !
|
||||||
|
\end{itemize}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\section*{Exercice 1 : Classification avec 5 zones}
|
||||||
|
|
||||||
|
Voici des points répartis en 5 zones de couleurs différentes. Le point noir ($\star$) est à classifier.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=1.1]
|
||||||
|
% Grille
|
||||||
|
\draw[gray!30, step=1] (0,0) grid (10,10);
|
||||||
|
|
||||||
|
% Cadre
|
||||||
|
\draw[thick] (0,0) rectangle (10,10);
|
||||||
|
|
||||||
|
% Zone 1 (Rouge) - En haut à gauche
|
||||||
|
\foreach \point in {(1,9), (1.5,8.5), (2,9.5), (1,8), (2.5,8.5), (1.5,7.5)} {
|
||||||
|
\fill[region1] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone 2 (Bleu) - En haut à droite
|
||||||
|
\foreach \point in {(8,9), (8.5,8.5), (9,9.5), (8,8), (9.5,8.5), (8.5,7.5)} {
|
||||||
|
\fill[region2] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone 3 (Vert) - En bas à gauche
|
||||||
|
\foreach \point in {(1,2), (1.5,1.5), (2,2.5), (1,1), (2.5,1.5), (1.5,2.5)} {
|
||||||
|
\fill[region3] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone 4 (Jaune) - En bas à droite
|
||||||
|
\foreach \point in {(8,2), (8.5,1.5), (9,2.5), (8,1), (9.5,1.5), (8.5,2.5)} {
|
||||||
|
\fill[region4] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone 5 (Violet) - Au centre
|
||||||
|
\foreach \point in {(5,5), (5.5,5.5), (4.5,5.5), (5.5,4.5), (4.5,4.5), (5,6)} {
|
||||||
|
\fill[region5] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Point à classifier (étoile noire)
|
||||||
|
\node[star,star points=5,star point ratio=2.5,fill=black,draw=black,thick,minimum size=0.6cm] at (6.5,6) {};
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
% Légende
|
||||||
|
\begin{tabular}{ccccccccc}
|
||||||
|
\textcolor{region1}{$\bullet$} Zone 1 & \quad &
|
||||||
|
\textcolor{region2}{$\bullet$} Zone 2 & \quad &
|
||||||
|
\textcolor{region3}{$\bullet$} Zone 3 & \quad &
|
||||||
|
\textcolor{region4}{$\bullet$} Zone 4 & \quad &
|
||||||
|
\textcolor{region5}{$\bullet$} Zone 5
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{Questions avec k = 3 :}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Identifiez les 3 points les plus proches du point noir $\star$. Tracez les distances.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
Les 3 plus proches : Zone \underline{\hspace{1cm}}, Zone \underline{\hspace{1cm}}, Zone \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Comptez les votes pour chaque zone parmi ces 3 voisins :
|
||||||
|
|
||||||
|
\vspace{0.2cm}
|
||||||
|
Zone 1 : \underline{\hspace{1cm}} \quad Zone 2 : \underline{\hspace{1cm}} \quad Zone 3 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
Zone 4 : \underline{\hspace{1cm}} \quad Zone 5 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Quelle est la zone majoritaire ? \underline{\hspace{4cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Y a-t-il égalité entre plusieurs zones ? \underline{\hspace{4cm}}
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
% ============= PAGE 2 =============
|
||||||
|
%\newpage
|
||||||
|
|
||||||
|
\section*{Exercice 2 : Influence de k avec plusieurs classes}
|
||||||
|
|
||||||
|
Reprenez le même graphique que l'exercice 1.
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{a) Avec k = 5 (5 voisins)}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Listez les 5 points les plus proches :
|
||||||
|
|
||||||
|
\vspace{0.2cm}
|
||||||
|
Zone \underline{\hspace{1.5cm}}, Zone \underline{\hspace{1.5cm}}, Zone \underline{\hspace{1.5cm}},
|
||||||
|
|
||||||
|
Zone \underline{\hspace{1.5cm}}, Zone \underline{\hspace{1.5cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Votes par zone :
|
||||||
|
|
||||||
|
\vspace{0.2cm}
|
||||||
|
Zone 1 : \underline{\hspace{1cm}} \quad Zone 2 : \underline{\hspace{1cm}} \quad Zone 3 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
Zone 4 : \underline{\hspace{1cm}} \quad Zone 5 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Classification du point noir : Zone \underline{\hspace{3cm}}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
|
||||||
|
\subsection*{b) Avec k = 7 (7 voisins)}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Votes par zone :
|
||||||
|
|
||||||
|
\vspace{0.2cm}
|
||||||
|
Zone 1 : \underline{\hspace{1cm}} \quad Zone 2 : \underline{\hspace{1cm}} \quad Zone 3 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
Zone 4 : \underline{\hspace{1cm}} \quad Zone 5 : \underline{\hspace{1cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Classification du point noir : Zone \underline{\hspace{3cm}}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightyellow,colframe=orange!75!black,title=\textbf{Réflexion : Plusieurs classes}]
|
||||||
|
|
||||||
|
\textbf{1. Qu'est-ce qui change par rapport à 2 classes seulement ?}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{2. Peut-il y avoir des égalités entre zones ? Donnez un exemple.}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{3. Comment résoudre une égalité ?}
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
% ============= PAGE 3 =============
|
||||||
|
%\newpage
|
||||||
|
|
||||||
|
\section*{Exercice 3 : Cas complexe avec 4 zones}
|
||||||
|
|
||||||
|
Voici une nouvelle situation avec 4 zones différentes. Classifiez le point $\star$ avec k = 5.
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=1.2]
|
||||||
|
% Grille
|
||||||
|
\draw[gray!30, step=1] (0,0) grid (10,10);
|
||||||
|
|
||||||
|
% Cadre
|
||||||
|
\draw[thick] (0,0) rectangle (10,10);
|
||||||
|
|
||||||
|
% Zone A (Rouge) - Dispersée
|
||||||
|
\foreach \point in {(1,8), (2,7), (1,6), (3,8.5), (2.5,6.5), (1.5,9)} {
|
||||||
|
\fill[region1] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone B (Bleu) - Coin supérieur droit
|
||||||
|
\foreach \point in {(8,8), (9,8.5), (8.5,7.5), (9,9), (8,9.5), (7.5,8)} {
|
||||||
|
\fill[region2] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone C (Vert) - En bas
|
||||||
|
\foreach \point in {(3,2), (4,1.5), (5,2), (6,1.5), (4,2.5), (5,1)} {
|
||||||
|
\fill[region3] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Zone D (Violet) - Centre-droit
|
||||||
|
\foreach \point in {(6,5), (7,5.5), (6.5,4.5), (7.5,5), (6,6), (7,6.5)} {
|
||||||
|
\fill[region5] \point circle (0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
% Point à classifier
|
||||||
|
\node[star,star points=5,star point ratio=2.5,fill=black,draw=black,thick,minimum size=0.6cm] at (5.5,5.5) {};
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
% Légende
|
||||||
|
\begin{tabular}{ccccccc}
|
||||||
|
\textcolor{region1}{$\bullet$} Zone A & \quad &
|
||||||
|
\textcolor{region2}{$\bullet$} Zone B & \quad &
|
||||||
|
\textcolor{region3}{$\bullet$} Zone C & \quad &
|
||||||
|
\textcolor{region5}{$\bullet$} Zone D
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{Travail à faire :}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Identifiez les 5 plus proches voisins et tracez les distances sur le graphique
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Complétez le tableau de votes :
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{|c|c|c|c|}
|
||||||
|
\hline
|
||||||
|
Zone A & Zone B & Zone C & Zone D \\
|
||||||
|
\hline
|
||||||
|
\hspace{1.5cm} & \hspace{1.5cm} & \hspace{1.5cm} & \hspace{1.5cm} \\[0.5cm]
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Classification finale : Zone \underline{\hspace{4cm}}
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
\item Cette classification vous semble-t-elle cohérente visuellement ? Pourquoi ?
|
||||||
|
|
||||||
|
\vspace{0.8cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
% ============= PAGE 4 =============
|
||||||
|
%\newpage
|
||||||
|
|
||||||
|
\section*{Exercice 4 : Création libre}
|
||||||
|
|
||||||
|
Créez votre propre situation avec au moins 3 zones différentes.
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=1.3]
|
||||||
|
% Grille
|
||||||
|
\draw[gray!20, step=1] (0,0) grid (12,12);
|
||||||
|
|
||||||
|
% Cadre
|
||||||
|
\draw[very thick] (0,0) rectangle (12,12);
|
||||||
|
|
||||||
|
% Graduations
|
||||||
|
\foreach \x in {0,2,4,6,8,10,12} {
|
||||||
|
\node[below] at (\x,-0.2) {\small \x};
|
||||||
|
}
|
||||||
|
\foreach \y in {0,2,4,6,8,10,12} {
|
||||||
|
\node[left] at (-0.2,\y) {\small \y};
|
||||||
|
}
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightblue,colframe=blue!75!black,title=\textbf{Instructions}]
|
||||||
|
\begin{itemize}
|
||||||
|
\item Choisissez 3 à 5 zones (utilisez des couleurs différentes)
|
||||||
|
\item Placez au moins 5 points par zone
|
||||||
|
\item Placez une étoile noire (point à classifier)
|
||||||
|
\item Utilisez k = 5 et déterminez la zone du point noir
|
||||||
|
\end{itemize}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\textbf{Vos zones :}
|
||||||
|
|
||||||
|
Zone 1 : \underline{\hspace{3cm}} (couleur : \underline{\hspace{2cm}})
|
||||||
|
|
||||||
|
Zone 2 : \underline{\hspace{3cm}} (couleur : \underline{\hspace{2cm}})
|
||||||
|
|
||||||
|
Zone 3 : \underline{\hspace{3cm}} (couleur : \underline{\hspace{2cm}})
|
||||||
|
|
||||||
|
\vspace{0.3cm}
|
||||||
|
|
||||||
|
\textbf{Classification avec k = 5 :} Zone \underline{\hspace{4cm}}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
\section*{Pour aller plus loin}
|
||||||
|
|
||||||
|
\subsection*{Applications avec plusieurs classes}
|
||||||
|
|
||||||
|
L'algorithme k-NN avec plusieurs classes est utilisé pour :
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Reconnaissance de chiffres} : Classifier 0, 1, 2, ..., 9 (10 classes)
|
||||||
|
\item \textbf{Classification de fleurs} : Différentes espèces (iris, rose, tulipe...)
|
||||||
|
\item \textbf{Zonage géographique} : Micro-régions, quartiers, zones climatiques
|
||||||
|
\item \textbf{Diagnostic médical} : Plusieurs types de maladies possibles
|
||||||
|
\item \textbf{Reconnaissance vocale} : Identifier différents phonèmes ou mots
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\subsection*{Défis avec plusieurs classes}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item \textbf{Égalités plus fréquentes} : Avec 2 classes, égalité rare. Avec 5 classes, beaucoup plus probable !
|
||||||
|
|
||||||
|
\item \textbf{Choix de k important} : Si k est trop petit, risque de ne pas capturer la diversité. Si trop grand, perd la précision locale.
|
||||||
|
|
||||||
|
\item \textbf{Classes déséquilibrées} : Si une zone a beaucoup plus de points qu'une autre, elle sera sur-représentée.
|
||||||
|
|
||||||
|
\item \textbf{Frontières complexes} : Avec plusieurs zones, les frontières peuvent être très irrégulières.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\vspace{0.5cm}
|
||||||
|
|
||||||
|
\begin{tcolorbox}[colback=lightyellow,colframe=orange!75!black,title=\textbf{Question finale}]
|
||||||
|
Pourquoi est-il préférable d'utiliser un \textit{k} impair lorsqu'on a un nombre pair de classes ?
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
|
||||||
|
\vspace{0.4cm}
|
||||||
|
\underline{\hspace{14cm}}
|
||||||
|
\end{tcolorbox}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
492
activite2/knn_microregions_animation.html
Normal file
492
activite2/knn_microregions_animation.html
Normal file
|
|
@ -0,0 +1,492 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>k-NN Animation - Micro-régions</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
cursor: crosshair;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #555;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
width: 100%;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #ddd;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-webkit-slider-thumb {
|
||||||
|
appearance: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #667eea;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"]::-moz-range-thumb {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #667eea;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-display {
|
||||||
|
display: inline-block;
|
||||||
|
background: #667eea;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-circle {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.votes {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
margin: 15px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-box {
|
||||||
|
padding: 15px 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 100px;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-count {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vote-label {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-reset {
|
||||||
|
background: #f44336;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-random {
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions {
|
||||||
|
background: #fff3cd;
|
||||||
|
border-left: 4px solid #ffc107;
|
||||||
|
padding: 15px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>🎯 Animation k-NN : Classification multi-zones</h1>
|
||||||
|
<p class="subtitle">Algorithme des k plus proches voisins avec plusieurs classes</p>
|
||||||
|
|
||||||
|
<div class="instructions">
|
||||||
|
<h3>📋 Instructions</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Cliquez</strong> sur le graphique pour placer un nouveau point</li>
|
||||||
|
<li><strong>Ajustez le curseur k</strong> pour voir l'impact du nombre de voisins</li>
|
||||||
|
<li>Observez comment les <strong>votes</strong> se répartissent entre les zones</li>
|
||||||
|
<li>Les lignes colorées montrent les <strong>k plus proches voisins</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<canvas id="canvas" width="800" height="600"></canvas>
|
||||||
|
|
||||||
|
<div class="legend" id="legend"></div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>
|
||||||
|
Nombre de voisins (k) :
|
||||||
|
<span class="value-display" id="kValue">5</span>
|
||||||
|
</label>
|
||||||
|
<input type="range" id="kSlider" min="1" max="21" value="5" step="2">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="result" id="result">
|
||||||
|
Cliquez sur le graphique pour classifier un point
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="votes" id="votes"></div>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<button class="btn-random" onclick="placeRandomPoint()">🎲 Point Aléatoire</button>
|
||||||
|
<button class="btn-reset" onclick="resetPoint()">🔄 Réinitialiser</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('canvas');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const kSlider = document.getElementById('kSlider');
|
||||||
|
const kValue = document.getElementById('kValue');
|
||||||
|
const result = document.getElementById('result');
|
||||||
|
const votesDiv = document.getElementById('votes');
|
||||||
|
const legendDiv = document.getElementById('legend');
|
||||||
|
|
||||||
|
// Définition des zones (micro-régions)
|
||||||
|
const zones = [
|
||||||
|
{ name: 'Alta Rocca', color: '#e74c3c', shortName: 'Alta Rocca' },
|
||||||
|
{ name: 'Balagne', color: '#3498db', shortName: 'Balagne' },
|
||||||
|
{ name: 'Centre Corse', color: '#2ecc71', shortName: 'Centre' },
|
||||||
|
{ name: 'Extrême Sud', color: '#f39c12', shortName: 'Sud' },
|
||||||
|
{ name: 'Cap Corse', color: '#9b59b6', shortName: 'Cap' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Points d'apprentissage (générés automatiquement par zone)
|
||||||
|
const trainingPoints = [];
|
||||||
|
|
||||||
|
// Zone 1 - Alta Rocca (rouge, bas gauche)
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
trainingPoints.push({
|
||||||
|
x: 100 + Math.random() * 150,
|
||||||
|
y: 400 + Math.random() * 150,
|
||||||
|
zone: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone 2 - Balagne (bleu, haut gauche)
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
trainingPoints.push({
|
||||||
|
x: 100 + Math.random() * 150,
|
||||||
|
y: 50 + Math.random() * 150,
|
||||||
|
zone: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone 3 - Centre Corse (vert, centre)
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
trainingPoints.push({
|
||||||
|
x: 300 + Math.random() * 200,
|
||||||
|
y: 200 + Math.random() * 200,
|
||||||
|
zone: 2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone 4 - Extrême Sud (jaune, bas droite)
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
trainingPoints.push({
|
||||||
|
x: 550 + Math.random() * 150,
|
||||||
|
y: 400 + Math.random() * 150,
|
||||||
|
zone: 3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone 5 - Cap Corse (violet, haut droite)
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
trainingPoints.push({
|
||||||
|
x: 550 + Math.random() * 150,
|
||||||
|
y: 50 + Math.random() * 150,
|
||||||
|
zone: 4
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let testPoint = null;
|
||||||
|
let k = 5;
|
||||||
|
|
||||||
|
// Créer la légende
|
||||||
|
function createLegend() {
|
||||||
|
legendDiv.innerHTML = '';
|
||||||
|
zones.forEach(zone => {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'legend-item';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div class="legend-circle" style="background: ${zone.color};"></div>
|
||||||
|
<span>${zone.name}</span>
|
||||||
|
`;
|
||||||
|
legendDiv.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function distance(p1, p2) {
|
||||||
|
return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findKNearest(point, k) {
|
||||||
|
const distances = trainingPoints.map(p => ({
|
||||||
|
point: p,
|
||||||
|
dist: distance(point, p)
|
||||||
|
}));
|
||||||
|
|
||||||
|
distances.sort((a, b) => a.dist - b.dist);
|
||||||
|
return distances.slice(0, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
function classify(point, k) {
|
||||||
|
const nearest = findKNearest(point, k);
|
||||||
|
const votes = {};
|
||||||
|
|
||||||
|
zones.forEach((_, idx) => votes[idx] = 0);
|
||||||
|
|
||||||
|
nearest.forEach(n => {
|
||||||
|
votes[n.point.zone]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trouver la zone avec le plus de votes
|
||||||
|
let maxVotes = -1;
|
||||||
|
let predictedZone = -1;
|
||||||
|
|
||||||
|
for (let zone in votes) {
|
||||||
|
if (votes[zone] > maxVotes) {
|
||||||
|
maxVotes = votes[zone];
|
||||||
|
predictedZone = parseInt(zone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
zone: predictedZone,
|
||||||
|
votes: votes,
|
||||||
|
nearest: nearest
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Dessiner les points d'apprentissage
|
||||||
|
trainingPoints.forEach(p => {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(p.x, p.y, 6, 0, 2 * Math.PI);
|
||||||
|
ctx.fillStyle = zones[p.zone].color;
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#333';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.stroke();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Si un point test existe
|
||||||
|
if (testPoint) {
|
||||||
|
const classification = classify(testPoint, k);
|
||||||
|
|
||||||
|
// Dessiner les lignes vers les k plus proches voisins
|
||||||
|
classification.nearest.forEach((n, index) => {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(testPoint.x, testPoint.y);
|
||||||
|
ctx.lineTo(n.point.x, n.point.y);
|
||||||
|
ctx.strokeStyle = zones[n.point.zone].color;
|
||||||
|
ctx.globalAlpha = 0.3 + 0.7 * (k - index) / k;
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Dessiner un cercle autour du k-ième plus proche voisin
|
||||||
|
if (classification.nearest.length > 0) {
|
||||||
|
const maxDist = classification.nearest[classification.nearest.length - 1].dist;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(testPoint.x, testPoint.y, maxDist, 0, 2 * Math.PI);
|
||||||
|
ctx.strokeStyle = 'rgba(0, 0, 0, 0.2)';
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.setLineDash([5, 5]);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.setLineDash([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner le point test
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(testPoint.x, testPoint.y, 12, 0, 2 * Math.PI);
|
||||||
|
ctx.fillStyle = '#95a5a6';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#000';
|
||||||
|
ctx.lineWidth = 3;
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// Afficher le résultat
|
||||||
|
displayResults(classification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayResults(classification) {
|
||||||
|
const zoneName = zones[classification.zone].name;
|
||||||
|
const zoneColor = zones[classification.zone].color;
|
||||||
|
|
||||||
|
result.innerHTML = `Classification : <span style="color: ${zoneColor};">${zoneName}</span>`;
|
||||||
|
result.style.background = zoneColor + '22';
|
||||||
|
|
||||||
|
// Afficher les votes
|
||||||
|
votesDiv.innerHTML = '';
|
||||||
|
zones.forEach((zone, idx) => {
|
||||||
|
const voteBox = document.createElement('div');
|
||||||
|
voteBox.className = 'vote-box';
|
||||||
|
voteBox.style.background = zone.color + '22';
|
||||||
|
voteBox.style.borderColor = classification.zone === idx ? zone.color : 'transparent';
|
||||||
|
|
||||||
|
const voteCount = classification.votes[idx] || 0;
|
||||||
|
|
||||||
|
voteBox.innerHTML = `
|
||||||
|
<div class="vote-count" style="color: ${zone.color};">${voteCount}</div>
|
||||||
|
<div class="vote-label">${zone.shortName}</div>
|
||||||
|
`;
|
||||||
|
votesDiv.appendChild(voteBox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.addEventListener('click', (e) => {
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
testPoint = {
|
||||||
|
x: e.clientX - rect.left,
|
||||||
|
y: e.clientY - rect.top
|
||||||
|
};
|
||||||
|
draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
kSlider.addEventListener('input', (e) => {
|
||||||
|
k = parseInt(e.target.value);
|
||||||
|
kValue.textContent = k;
|
||||||
|
draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
function placeRandomPoint() {
|
||||||
|
testPoint = {
|
||||||
|
x: Math.random() * (canvas.width - 100) + 50,
|
||||||
|
y: Math.random() * (canvas.height - 100) + 50
|
||||||
|
};
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetPoint() {
|
||||||
|
testPoint = null;
|
||||||
|
result.innerHTML = 'Cliquez sur le graphique pour classifier un point';
|
||||||
|
result.style.background = '#f0f0f0';
|
||||||
|
votesDiv.innerHTML = '';
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation
|
||||||
|
createLegend();
|
||||||
|
draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
76
menu.html
Normal file
76
menu.html
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Menu déroulant</title>
|
||||||
|
<style>
|
||||||
|
/* Styles de base pour le menu */
|
||||||
|
.menu {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu li {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu a {
|
||||||
|
display: block;
|
||||||
|
padding: 15px 20px;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu a:hover {
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Styles pour le sous-menu */
|
||||||
|
.sous-menu {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
background-color: #444;
|
||||||
|
min-width: 200px;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Afficher le sous-menu au survol */
|
||||||
|
.menu li:hover .sous-menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sous-menu a {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ul class="menu">
|
||||||
|
<li><a href="#">Accueil</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="#">Produits</a>
|
||||||
|
<ul class="sous-menu">
|
||||||
|
<li><a href="#">Produit 1</a></li>
|
||||||
|
<li><a href="#">Produit 2</a></li>
|
||||||
|
<li><a href="#">Produit 3</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#">Services</a>
|
||||||
|
<ul class="sous-menu">
|
||||||
|
<li><a href="#">Service A</a></li>
|
||||||
|
<li><a href="#">Service B</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
quick-push.sh
Executable file
4
quick-push.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
git add .
|
||||||
|
git commit -m "${1:-Auto-update: $(date '+%Y-%m-%d %H:%M:%S')}"
|
||||||
|
git push
|
||||||
Loading…
Add table
Add a link
Reference in a new issue